8168386: Fix jdeps verbose options
Reviewed-by: dfuchs, lancea
This commit is contained in:
parent
8899d19210
commit
40e24f2e56
@ -25,8 +25,10 @@
|
|||||||
|
|
||||||
package com.sun.tools.jdeps;
|
package com.sun.tools.jdeps;
|
||||||
|
|
||||||
|
import com.sun.tools.jdeps.Analyzer.Type;
|
||||||
import static com.sun.tools.jdeps.Analyzer.Type.*;
|
import static com.sun.tools.jdeps.Analyzer.Type.*;
|
||||||
import static com.sun.tools.jdeps.JdepsWriter.*;
|
import static com.sun.tools.jdeps.JdepsWriter.*;
|
||||||
|
import static java.util.stream.Collectors.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@ -111,6 +113,10 @@ class JdepsTask {
|
|||||||
this.aliases = aliases;
|
this.aliases = aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Option(boolean hasArg, CommandOption cmd) {
|
||||||
|
this(hasArg, cmd.names());
|
||||||
|
}
|
||||||
|
|
||||||
boolean isHidden() {
|
boolean isHidden() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -144,25 +150,46 @@ class JdepsTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CommandOption {
|
||||||
|
ANALYZE_DEPS(""),
|
||||||
|
GENERATE_DOT_FILE("-dotoutput", "--dot-output"),
|
||||||
|
GENERATE_MODULE_INFO("--generate-module-info"),
|
||||||
|
LIST_DEPS("--list-deps"),
|
||||||
|
LIST_REDUCED_DEPS("--list-reduced-deps"),
|
||||||
|
CHECK_MODULES("--check");
|
||||||
|
|
||||||
|
private final String[] names;
|
||||||
|
CommandOption(String... names) {
|
||||||
|
this.names = names;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] names() {
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return names[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Option[] recognizedOptions = {
|
static Option[] recognizedOptions = {
|
||||||
new Option(false, "-h", "-?", "-help", "--help") {
|
new Option(false, "-h", "-?", "-help", "--help") {
|
||||||
void process(JdepsTask task, String opt, String arg) {
|
void process(JdepsTask task, String opt, String arg) {
|
||||||
task.options.help = true;
|
task.options.help = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Option(true, "-dotoutput", "--dot-output") {
|
new Option(true, CommandOption.GENERATE_DOT_FILE) {
|
||||||
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
||||||
Path p = Paths.get(arg);
|
if (task.command != null) {
|
||||||
if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
|
throw new BadArgs("err.command.set", task.command, opt);
|
||||||
throw new BadArgs("err.invalid.path", arg);
|
|
||||||
}
|
}
|
||||||
task.options.dotOutputDir = Paths.get(arg);;
|
task.command = task.genDotFile(Paths.get(arg));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Option(false, "-s", "-summary") {
|
new Option(false, "-s", "-summary") {
|
||||||
void process(JdepsTask task, String opt, String arg) {
|
void process(JdepsTask task, String opt, String arg) {
|
||||||
task.options.showSummary = true;
|
task.options.showSummary = true;
|
||||||
task.options.verbose = SUMMARY;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Option(false, "-v", "-verbose",
|
new Option(false, "-v", "-verbose",
|
||||||
@ -196,35 +223,48 @@ class JdepsTask {
|
|||||||
task.options.apiOnly = true;
|
task.options.apiOnly = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Option(true, "--check") {
|
|
||||||
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
|
||||||
Set<String> mods = Set.of(arg.split(","));
|
|
||||||
task.options.checkModuleDeps = mods;
|
|
||||||
task.options.addmods.addAll(mods);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Option(true, "--generate-module-info") {
|
|
||||||
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
|
||||||
Path p = Paths.get(arg);
|
|
||||||
if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
|
|
||||||
throw new BadArgs("err.invalid.path", arg);
|
|
||||||
}
|
|
||||||
task.options.genModuleInfo = Paths.get(arg);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Option(false, "-jdkinternals", "--jdk-internals") {
|
new Option(false, "-jdkinternals", "--jdk-internals") {
|
||||||
void process(JdepsTask task, String opt, String arg) {
|
void process(JdepsTask task, String opt, String arg) {
|
||||||
task.options.findJDKInternals = true;
|
task.options.findJDKInternals = true;
|
||||||
task.options.verbose = CLASS;
|
|
||||||
if (task.options.includePattern == null) {
|
if (task.options.includePattern == null) {
|
||||||
task.options.includePattern = Pattern.compile(".*");
|
task.options.includePattern = Pattern.compile(".*");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Option(false, "--list-deps", "--list-reduced-deps") {
|
|
||||||
void process(JdepsTask task, String opt, String arg) {
|
new Option(true, CommandOption.CHECK_MODULES) {
|
||||||
task.options.showModulesAddExports = true;
|
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
||||||
task.options.reduced = opt.equals("--list-reduced-deps");
|
if (task.command != null) {
|
||||||
|
throw new BadArgs("err.command.set", task.command, opt);
|
||||||
|
}
|
||||||
|
Set<String> mods = Set.of(arg.split(","));
|
||||||
|
task.options.addmods.addAll(mods);
|
||||||
|
task.command = task.checkModuleDeps(mods);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Option(true, CommandOption.GENERATE_MODULE_INFO) {
|
||||||
|
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
||||||
|
if (task.command != null) {
|
||||||
|
throw new BadArgs("err.command.set", task.command, opt);
|
||||||
|
}
|
||||||
|
task.command = task.genModuleInfo(Paths.get(arg));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Option(false, CommandOption.LIST_DEPS) {
|
||||||
|
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
||||||
|
if (task.command != null) {
|
||||||
|
throw new BadArgs("err.command.set", task.command, opt);
|
||||||
|
}
|
||||||
|
task.command = task.listModuleDeps(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Option(false, CommandOption.LIST_REDUCED_DEPS) {
|
||||||
|
void process(JdepsTask task, String opt, String arg) throws BadArgs {
|
||||||
|
if (task.command != null) {
|
||||||
|
throw new BadArgs("err.command.set", task.command, opt);
|
||||||
|
}
|
||||||
|
task.command = task.listModuleDeps(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -419,6 +459,7 @@ class JdepsTask {
|
|||||||
private final Options options = new Options();
|
private final Options options = new Options();
|
||||||
private final List<String> inputArgs = new ArrayList<>();
|
private final List<String> inputArgs = new ArrayList<>();
|
||||||
|
|
||||||
|
private Command command;
|
||||||
private PrintWriter log;
|
private PrintWriter log;
|
||||||
void setLog(PrintWriter out) {
|
void setLog(PrintWriter out) {
|
||||||
log = out;
|
log = out;
|
||||||
@ -445,55 +486,30 @@ class JdepsTask {
|
|||||||
if (options.version || options.fullVersion) {
|
if (options.version || options.fullVersion) {
|
||||||
showVersion(options.fullVersion);
|
showVersion(options.fullVersion);
|
||||||
}
|
}
|
||||||
|
if (options.help || options.version || options.fullVersion) {
|
||||||
|
return EXIT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (!inputArgs.isEmpty() && options.rootModule != null) {
|
if (!inputArgs.isEmpty() && options.rootModule != null) {
|
||||||
reportError("err.invalid.arg.for.option", "-m");
|
reportError("err.invalid.arg.for.option", "-m");
|
||||||
}
|
}
|
||||||
if (inputArgs.isEmpty() && options.addmods.isEmpty() && options.includePattern == null
|
|
||||||
&& options.includeSystemModulePattern == null && options.checkModuleDeps == null) {
|
|
||||||
if (options.help || options.version || options.fullVersion) {
|
|
||||||
return EXIT_OK;
|
|
||||||
} else {
|
|
||||||
showHelp();
|
|
||||||
return EXIT_CMDERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (options.genModuleInfo != null) {
|
|
||||||
if (options.dotOutputDir != null || options.classpath != null || options.hasFilter()) {
|
|
||||||
showHelp();
|
|
||||||
return EXIT_CMDERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.numFilters() > 1) {
|
if (options.numFilters() > 1) {
|
||||||
reportError("err.invalid.filters");
|
reportError("err.invalid.filters");
|
||||||
return EXIT_CMDERR;
|
return EXIT_CMDERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.inverse && options.depth != 1) {
|
// default command to analyze dependences
|
||||||
reportError("err.invalid.inverse.option", "-R");
|
if (command == null) {
|
||||||
return EXIT_CMDERR;
|
command = analyzeDeps();
|
||||||
}
|
}
|
||||||
|
if (!command.checkOptions()) {
|
||||||
if (options.inverse && options.numFilters() == 0) {
|
|
||||||
reportError("err.invalid.filters");
|
|
||||||
return EXIT_CMDERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((options.findJDKInternals) && (options.hasFilter() || options.showSummary)) {
|
|
||||||
showHelp();
|
|
||||||
return EXIT_CMDERR;
|
|
||||||
}
|
|
||||||
if (options.showSummary && options.verbose != SUMMARY) {
|
|
||||||
showHelp();
|
|
||||||
return EXIT_CMDERR;
|
|
||||||
}
|
|
||||||
if (options.checkModuleDeps != null && !inputArgs.isEmpty()) {
|
|
||||||
reportError("err.invalid.module.option", inputArgs, "--check");
|
|
||||||
return EXIT_CMDERR;
|
return EXIT_CMDERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean ok = run();
|
boolean ok = run();
|
||||||
return ok ? EXIT_OK : EXIT_ERROR;
|
return ok ? EXIT_OK : EXIT_ERROR;
|
||||||
|
|
||||||
} catch (BadArgs|UncheckedBadArgs e) {
|
} catch (BadArgs|UncheckedBadArgs e) {
|
||||||
reportError(e.getKey(), e.getArgs());
|
reportError(e.getKey(), e.getArgs());
|
||||||
if (e.showUsage()) {
|
if (e.showUsage()) {
|
||||||
@ -515,13 +531,14 @@ class JdepsTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean run() throws IOException {
|
boolean run() throws IOException {
|
||||||
try (JdepsConfiguration config = buildConfig()) {
|
try (JdepsConfiguration config = buildConfig(command.allModules())) {
|
||||||
|
|
||||||
// detect split packages
|
// detect split packages
|
||||||
config.splitPackages().entrySet().stream()
|
config.splitPackages().entrySet()
|
||||||
|
.stream()
|
||||||
.sorted(Map.Entry.comparingByKey())
|
.sorted(Map.Entry.comparingByKey())
|
||||||
.forEach(e -> System.out.format("split package: %s %s%n", e.getKey(),
|
.forEach(e -> System.out.format("split package: %s %s%n", e.getKey(),
|
||||||
e.getValue().toString()));
|
e.getValue().toString()));
|
||||||
|
|
||||||
// check if any module specified in --require is missing
|
// check if any module specified in --require is missing
|
||||||
Stream.concat(options.addmods.stream(), options.requires.stream())
|
Stream.concat(options.addmods.stream(), options.requires.stream())
|
||||||
@ -529,38 +546,11 @@ class JdepsTask {
|
|||||||
.forEach(mn -> config.findModule(mn).orElseThrow(() ->
|
.forEach(mn -> config.findModule(mn).orElseThrow(() ->
|
||||||
new UncheckedBadArgs(new BadArgs("err.module.not.found", mn))));
|
new UncheckedBadArgs(new BadArgs("err.module.not.found", mn))));
|
||||||
|
|
||||||
// --generate-module-info
|
return command.run(config);
|
||||||
if (options.genModuleInfo != null) {
|
|
||||||
return genModuleInfo(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
// --check
|
|
||||||
if (options.checkModuleDeps != null) {
|
|
||||||
return new ModuleAnalyzer(config, log, options.checkModuleDeps).run();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.showModulesAddExports) {
|
|
||||||
return new ModuleExportsAnalyzer(config,
|
|
||||||
dependencyFilter(config),
|
|
||||||
options.reduced,
|
|
||||||
log).run();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.dotOutputDir != null &&
|
|
||||||
(options.verbose == SUMMARY || options.verbose == MODULE) &&
|
|
||||||
!options.addmods.isEmpty() && inputArgs.isEmpty()) {
|
|
||||||
return new ModuleAnalyzer(config, log).genDotFiles(options.dotOutputDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.inverse) {
|
|
||||||
return analyzeInverseDeps(config);
|
|
||||||
} else {
|
|
||||||
return analyzeDeps(config);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private JdepsConfiguration buildConfig() throws IOException {
|
private JdepsConfiguration buildConfig(boolean allModules) throws IOException {
|
||||||
JdepsConfiguration.Builder builder =
|
JdepsConfiguration.Builder builder =
|
||||||
new JdepsConfiguration.Builder(options.systemModulePath);
|
new JdepsConfiguration.Builder(options.systemModulePath);
|
||||||
|
|
||||||
@ -568,7 +558,7 @@ class JdepsTask {
|
|||||||
.appModulePath(options.modulePath)
|
.appModulePath(options.modulePath)
|
||||||
.addmods(options.addmods);
|
.addmods(options.addmods);
|
||||||
|
|
||||||
if (options.checkModuleDeps != null || options.showModulesAddExports) {
|
if (allModules) {
|
||||||
// check all system modules in the image
|
// check all system modules in the image
|
||||||
builder.allModules();
|
builder.allModules();
|
||||||
}
|
}
|
||||||
@ -592,148 +582,420 @@ class JdepsTask {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean analyzeDeps(JdepsConfiguration config) throws IOException {
|
// ---- factory methods to create a Command
|
||||||
// output result
|
|
||||||
final JdepsWriter writer;
|
|
||||||
if (options.dotOutputDir != null) {
|
|
||||||
writer = new DotFileWriter(options.dotOutputDir,
|
|
||||||
options.verbose,
|
|
||||||
options.showProfile,
|
|
||||||
options.showModule,
|
|
||||||
options.showLabel);
|
|
||||||
} else {
|
|
||||||
writer = new SimpleWriter(log,
|
|
||||||
options.verbose,
|
|
||||||
options.showProfile,
|
|
||||||
options.showModule);
|
|
||||||
}
|
|
||||||
|
|
||||||
// analyze the dependencies
|
private AnalyzeDeps analyzeDeps() throws BadArgs {
|
||||||
DepsAnalyzer analyzer = new DepsAnalyzer(config,
|
return options.inverse ? new InverseAnalyzeDeps()
|
||||||
dependencyFilter(config),
|
: new AnalyzeDeps();
|
||||||
writer,
|
|
||||||
options.verbose,
|
|
||||||
options.apiOnly);
|
|
||||||
|
|
||||||
boolean ok = analyzer.run(options.compileTimeView, options.depth);
|
|
||||||
|
|
||||||
// print skipped entries, if any
|
|
||||||
if (!options.nowarning) {
|
|
||||||
analyzer.archives()
|
|
||||||
.forEach(archive -> archive.reader()
|
|
||||||
.skippedEntries().stream()
|
|
||||||
.forEach(name -> warning("warn.skipped.entry", name)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.findJDKInternals && !options.nowarning) {
|
|
||||||
Map<String, String> jdkInternals = new TreeMap<>();
|
|
||||||
Set<String> deps = analyzer.dependences();
|
|
||||||
// find the ones with replacement
|
|
||||||
deps.forEach(cn -> replacementFor(cn).ifPresent(
|
|
||||||
repl -> jdkInternals.put(cn, repl))
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!deps.isEmpty()) {
|
|
||||||
log.println();
|
|
||||||
warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!jdkInternals.isEmpty()) {
|
|
||||||
log.println();
|
|
||||||
log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement");
|
|
||||||
log.format("%-40s %s%n", "----------------", "---------------------");
|
|
||||||
jdkInternals.entrySet().stream()
|
|
||||||
.forEach(e -> {
|
|
||||||
String key = e.getKey();
|
|
||||||
String[] lines = e.getValue().split("\\n");
|
|
||||||
for (String s : lines) {
|
|
||||||
log.format("%-40s %s%n", key, s);
|
|
||||||
key = "";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean analyzeInverseDeps(JdepsConfiguration config) throws IOException {
|
private GenDotFile genDotFile(Path dir) throws BadArgs {
|
||||||
JdepsWriter writer = new SimpleWriter(log,
|
if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
|
||||||
options.verbose,
|
throw new BadArgs("err.invalid.path", dir.toString());
|
||||||
options.showProfile,
|
}
|
||||||
options.showModule);
|
return new GenDotFile(dir);
|
||||||
|
|
||||||
InverseDepsAnalyzer analyzer = new InverseDepsAnalyzer(config,
|
|
||||||
dependencyFilter(config),
|
|
||||||
writer,
|
|
||||||
options.verbose,
|
|
||||||
options.apiOnly);
|
|
||||||
boolean ok = analyzer.run();
|
|
||||||
|
|
||||||
log.println();
|
|
||||||
if (!options.requires.isEmpty())
|
|
||||||
log.format("Inverse transitive dependences on %s%n", options.requires);
|
|
||||||
else
|
|
||||||
log.format("Inverse transitive dependences matching %s%n",
|
|
||||||
options.regex != null
|
|
||||||
? options.regex.toString()
|
|
||||||
: "packages " + options.packageNames);
|
|
||||||
|
|
||||||
analyzer.inverseDependences().stream()
|
|
||||||
.sorted(Comparator.comparing(this::sortPath))
|
|
||||||
.forEach(path -> log.println(path.stream()
|
|
||||||
.map(Archive::getName)
|
|
||||||
.collect(Collectors.joining(" <- "))));
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String sortPath(Deque<Archive> path) {
|
private GenModuleInfo genModuleInfo(Path dir) throws BadArgs {
|
||||||
return path.peekFirst().getName();
|
if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
|
||||||
|
throw new BadArgs("err.invalid.path", dir.toString());
|
||||||
|
}
|
||||||
|
return new GenModuleInfo(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean genModuleInfo(JdepsConfiguration config) throws IOException {
|
private ListModuleDeps listModuleDeps(boolean reduced) throws BadArgs {
|
||||||
// check if any JAR file contains unnamed package
|
return reduced ? new ListReducedDeps()
|
||||||
for (String arg : inputArgs) {
|
: new ListModuleDeps();
|
||||||
try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) {
|
}
|
||||||
Optional<String> classInUnnamedPackage =
|
|
||||||
reader.entries().stream()
|
|
||||||
.filter(n -> n.endsWith(".class"))
|
|
||||||
.filter(cn -> toPackageName(cn).isEmpty())
|
|
||||||
.findFirst();
|
|
||||||
|
|
||||||
if (classInUnnamedPackage.isPresent()) {
|
private CheckModuleDeps checkModuleDeps(Set<String> mods) throws BadArgs {
|
||||||
if (classInUnnamedPackage.get().equals("module-info.class")) {
|
return new CheckModuleDeps(mods);
|
||||||
reportError("err.genmoduleinfo.not.jarfile", arg);
|
}
|
||||||
} else {
|
|
||||||
reportError("err.genmoduleinfo.unnamed.package", arg);
|
abstract class Command {
|
||||||
}
|
final CommandOption option;
|
||||||
|
protected Command(CommandOption option) {
|
||||||
|
this.option = option;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns true if the command-line options are all valid;
|
||||||
|
* otherwise, returns false.
|
||||||
|
*/
|
||||||
|
abstract boolean checkOptions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do analysis
|
||||||
|
*/
|
||||||
|
abstract boolean run(JdepsConfiguration config) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Includes all modules on system module path and application module path
|
||||||
|
*/
|
||||||
|
boolean allModules() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return option.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analyze dependences
|
||||||
|
*/
|
||||||
|
class AnalyzeDeps extends Command {
|
||||||
|
JdepsWriter writer;
|
||||||
|
AnalyzeDeps() {
|
||||||
|
this(CommandOption.ANALYZE_DEPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnalyzeDeps(CommandOption option) {
|
||||||
|
super(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean checkOptions() {
|
||||||
|
if (options.findJDKInternals) {
|
||||||
|
// cannot set any filter, -verbose and -summary option
|
||||||
|
if (options.showSummary || options.verbose != null) {
|
||||||
|
reportError("err.invalid.options", "-summary or -verbose",
|
||||||
|
"-jdkinternals");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (options.hasFilter()) {
|
||||||
|
reportError("err.invalid.options", "--package, --regex, --require",
|
||||||
|
"-jdkinternals");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (options.showSummary) {
|
||||||
|
// -summary cannot use with -verbose option
|
||||||
|
if (options.verbose != null) {
|
||||||
|
reportError("err.invalid.options", "-v, -verbose", "-s, -summary");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inputArgs.isEmpty() && !options.hasSourcePath()) {
|
||||||
|
showHelp();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleInfoBuilder builder
|
/*
|
||||||
= new ModuleInfoBuilder(config, inputArgs, options.genModuleInfo);
|
* Default is to show package-level dependencies
|
||||||
boolean ok = builder.run();
|
*/
|
||||||
|
Type getAnalyzerType() {
|
||||||
|
if (options.showSummary)
|
||||||
|
return Type.SUMMARY;
|
||||||
|
|
||||||
if (!ok && !options.nowarning) {
|
if (options.findJDKInternals)
|
||||||
log.println("ERROR: missing dependencies");
|
return Type.CLASS;
|
||||||
builder.visitMissingDeps(
|
|
||||||
new Analyzer.Visitor() {
|
// default to package-level verbose
|
||||||
@Override
|
return options.verbose != null ? options.verbose : PACKAGE;
|
||||||
public void visitDependence(String origin, Archive originArchive,
|
}
|
||||||
String target, Archive targetArchive) {
|
|
||||||
if (builder.notFound(targetArchive))
|
@Override
|
||||||
log.format(" %-50s -> %-50s %s%n",
|
boolean run(JdepsConfiguration config) throws IOException {
|
||||||
origin, target, targetArchive.getName());
|
Type type = getAnalyzerType();
|
||||||
}
|
// default to package-level verbose
|
||||||
});
|
JdepsWriter writer = new SimpleWriter(log,
|
||||||
|
type,
|
||||||
|
options.showProfile,
|
||||||
|
options.showModule);
|
||||||
|
|
||||||
|
return run(config, writer, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean run(JdepsConfiguration config, JdepsWriter writer, Type type) throws IOException {
|
||||||
|
|
||||||
|
|
||||||
|
// analyze the dependencies
|
||||||
|
DepsAnalyzer analyzer = new DepsAnalyzer(config,
|
||||||
|
dependencyFilter(config),
|
||||||
|
writer,
|
||||||
|
type,
|
||||||
|
options.apiOnly);
|
||||||
|
|
||||||
|
boolean ok = analyzer.run(options.compileTimeView, options.depth);
|
||||||
|
|
||||||
|
// print skipped entries, if any
|
||||||
|
if (!options.nowarning) {
|
||||||
|
analyzer.archives()
|
||||||
|
.forEach(archive -> archive.reader()
|
||||||
|
.skippedEntries().stream()
|
||||||
|
.forEach(name -> warning("warn.skipped.entry", name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.findJDKInternals && !options.nowarning) {
|
||||||
|
Map<String, String> jdkInternals = new TreeMap<>();
|
||||||
|
Set<String> deps = analyzer.dependences();
|
||||||
|
// find the ones with replacement
|
||||||
|
deps.forEach(cn -> replacementFor(cn).ifPresent(
|
||||||
|
repl -> jdkInternals.put(cn, repl))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!deps.isEmpty()) {
|
||||||
|
log.println();
|
||||||
|
warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jdkInternals.isEmpty()) {
|
||||||
|
log.println();
|
||||||
|
log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement");
|
||||||
|
log.format("%-40s %s%n", "----------------", "---------------------");
|
||||||
|
jdkInternals.entrySet().stream()
|
||||||
|
.forEach(e -> {
|
||||||
|
String key = e.getKey();
|
||||||
|
String[] lines = e.getValue().split("\\n");
|
||||||
|
for (String s : lines) {
|
||||||
|
log.format("%-40s %s%n", key, s);
|
||||||
|
key = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toPackageName(String name) {
|
|
||||||
int i = name.lastIndexOf('/');
|
class InverseAnalyzeDeps extends AnalyzeDeps {
|
||||||
return i > 0 ? name.replace('/', '.').substring(0, i) : "";
|
InverseAnalyzeDeps() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean checkOptions() {
|
||||||
|
if (options.depth != 1) {
|
||||||
|
reportError("err.invalid.options", "-R", "--inverse");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.numFilters() == 0) {
|
||||||
|
reportError("err.filter.not.specified");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!super.checkOptions()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean run(JdepsConfiguration config) throws IOException {
|
||||||
|
Type type = getAnalyzerType();
|
||||||
|
|
||||||
|
InverseDepsAnalyzer analyzer =
|
||||||
|
new InverseDepsAnalyzer(config,
|
||||||
|
dependencyFilter(config),
|
||||||
|
writer,
|
||||||
|
type,
|
||||||
|
options.apiOnly);
|
||||||
|
boolean ok = analyzer.run();
|
||||||
|
|
||||||
|
log.println();
|
||||||
|
if (!options.requires.isEmpty())
|
||||||
|
log.format("Inverse transitive dependences on %s%n", options.requires);
|
||||||
|
else
|
||||||
|
log.format("Inverse transitive dependences matching %s%n",
|
||||||
|
options.regex != null
|
||||||
|
? options.regex.toString()
|
||||||
|
: "packages " + options.packageNames);
|
||||||
|
|
||||||
|
analyzer.inverseDependences().stream()
|
||||||
|
.sorted(Comparator.comparing(this::sortPath))
|
||||||
|
.forEach(path -> log.println(path.stream()
|
||||||
|
.map(Archive::getName)
|
||||||
|
.collect(joining(" <- "))));
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sortPath(Deque<Archive> path) {
|
||||||
|
return path.peekFirst().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class GenModuleInfo extends Command {
|
||||||
|
final Path dir;
|
||||||
|
GenModuleInfo(Path dir) {
|
||||||
|
super(CommandOption.GENERATE_MODULE_INFO);
|
||||||
|
this.dir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean checkOptions() {
|
||||||
|
if (options.classpath != null) {
|
||||||
|
reportError("err.invalid.options", "-classpath",
|
||||||
|
option);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (options.hasFilter()) {
|
||||||
|
reportError("err.invalid.options", "--package, --regex, --require",
|
||||||
|
option);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean run(JdepsConfiguration config) throws IOException {
|
||||||
|
// check if any JAR file contains unnamed package
|
||||||
|
for (String arg : inputArgs) {
|
||||||
|
try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) {
|
||||||
|
Optional<String> classInUnnamedPackage =
|
||||||
|
reader.entries().stream()
|
||||||
|
.filter(n -> n.endsWith(".class"))
|
||||||
|
.filter(cn -> toPackageName(cn).isEmpty())
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (classInUnnamedPackage.isPresent()) {
|
||||||
|
if (classInUnnamedPackage.get().equals("module-info.class")) {
|
||||||
|
reportError("err.genmoduleinfo.not.jarfile", arg);
|
||||||
|
} else {
|
||||||
|
reportError("err.genmoduleinfo.unnamed.package", arg);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleInfoBuilder builder
|
||||||
|
= new ModuleInfoBuilder(config, inputArgs, dir);
|
||||||
|
boolean ok = builder.run();
|
||||||
|
|
||||||
|
if (!ok && !options.nowarning) {
|
||||||
|
log.println("ERROR: missing dependencies");
|
||||||
|
builder.visitMissingDeps(
|
||||||
|
new Analyzer.Visitor() {
|
||||||
|
@Override
|
||||||
|
public void visitDependence(String origin, Archive originArchive,
|
||||||
|
String target, Archive targetArchive) {
|
||||||
|
if (builder.notFound(targetArchive))
|
||||||
|
log.format(" %-50s -> %-50s %s%n",
|
||||||
|
origin, target, targetArchive.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toPackageName(String name) {
|
||||||
|
int i = name.lastIndexOf('/');
|
||||||
|
return i > 0 ? name.replace('/', '.').substring(0, i) : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CheckModuleDeps extends Command {
|
||||||
|
final Set<String> modules;
|
||||||
|
CheckModuleDeps(Set<String> mods) {
|
||||||
|
super(CommandOption.CHECK_MODULES);
|
||||||
|
this.modules = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean checkOptions() {
|
||||||
|
if (!inputArgs.isEmpty()) {
|
||||||
|
reportError("err.invalid.options", inputArgs, "--check");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean run(JdepsConfiguration config) throws IOException {
|
||||||
|
if (!config.initialArchives().isEmpty()) {
|
||||||
|
String list = config.initialArchives().stream()
|
||||||
|
.map(Archive::getPathName).collect(joining(" "));
|
||||||
|
throw new UncheckedBadArgs(new BadArgs("err.invalid.options",
|
||||||
|
list, "--check"));
|
||||||
|
}
|
||||||
|
return new ModuleAnalyzer(config, log, modules).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allModules() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListReducedDeps extends ListModuleDeps {
|
||||||
|
ListReducedDeps() {
|
||||||
|
super(CommandOption.LIST_REDUCED_DEPS, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListModuleDeps extends Command {
|
||||||
|
final boolean reduced;
|
||||||
|
ListModuleDeps() {
|
||||||
|
this(CommandOption.LIST_DEPS, false);
|
||||||
|
}
|
||||||
|
ListModuleDeps(CommandOption option, boolean reduced) {
|
||||||
|
super(option);
|
||||||
|
this.reduced = reduced;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean checkOptions() {
|
||||||
|
if (options.showSummary || options.verbose != null) {
|
||||||
|
reportError("err.invalid.options", "-summary or -verbose",
|
||||||
|
option);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (options.findJDKInternals) {
|
||||||
|
reportError("err.invalid.options", "-jdkinternals",
|
||||||
|
option);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (inputArgs.isEmpty() && !options.hasSourcePath()) {
|
||||||
|
showHelp();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean run(JdepsConfiguration config) throws IOException {
|
||||||
|
return new ModuleExportsAnalyzer(config,
|
||||||
|
dependencyFilter(config),
|
||||||
|
reduced,
|
||||||
|
log).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allModules() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class GenDotFile extends AnalyzeDeps {
|
||||||
|
final Path dotOutputDir;
|
||||||
|
GenDotFile(Path dotOutputDir) {
|
||||||
|
super(CommandOption.GENERATE_DOT_FILE);
|
||||||
|
|
||||||
|
this.dotOutputDir = dotOutputDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean run(JdepsConfiguration config) throws IOException {
|
||||||
|
if ((options.showSummary || options.verbose == MODULE) &&
|
||||||
|
!options.addmods.isEmpty() && inputArgs.isEmpty()) {
|
||||||
|
// print module descriptor
|
||||||
|
return new ModuleAnalyzer(config, log).genDotFiles(dotOutputDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type = getAnalyzerType();
|
||||||
|
JdepsWriter writer = new DotFileWriter(dotOutputDir,
|
||||||
|
type,
|
||||||
|
options.showProfile,
|
||||||
|
options.showModule,
|
||||||
|
options.showLabel);
|
||||||
|
return run(config, writer, type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -875,14 +1137,11 @@ class JdepsTask {
|
|||||||
boolean showLabel;
|
boolean showLabel;
|
||||||
boolean findJDKInternals;
|
boolean findJDKInternals;
|
||||||
boolean nowarning = false;
|
boolean nowarning = false;
|
||||||
// default is to show package-level dependencies
|
Analyzer.Type verbose;
|
||||||
// and filter references from same package
|
// default filter references from same package
|
||||||
Analyzer.Type verbose = PACKAGE;
|
|
||||||
boolean filterSamePackage = true;
|
boolean filterSamePackage = true;
|
||||||
boolean filterSameArchive = false;
|
boolean filterSameArchive = false;
|
||||||
Pattern filterRegex;
|
Pattern filterRegex;
|
||||||
Path dotOutputDir;
|
|
||||||
Path genModuleInfo;
|
|
||||||
String classpath;
|
String classpath;
|
||||||
int depth = 1;
|
int depth = 1;
|
||||||
Set<String> requires = new HashSet<>();
|
Set<String> requires = new HashSet<>();
|
||||||
@ -892,15 +1151,17 @@ class JdepsTask {
|
|||||||
Pattern includeSystemModulePattern;
|
Pattern includeSystemModulePattern;
|
||||||
boolean inverse = false;
|
boolean inverse = false;
|
||||||
boolean compileTimeView = false;
|
boolean compileTimeView = false;
|
||||||
Set<String> checkModuleDeps;
|
|
||||||
String systemModulePath = System.getProperty("java.home");
|
String systemModulePath = System.getProperty("java.home");
|
||||||
String upgradeModulePath;
|
String upgradeModulePath;
|
||||||
String modulePath;
|
String modulePath;
|
||||||
String rootModule;
|
String rootModule;
|
||||||
Set<String> addmods = new HashSet<>();
|
Set<String> addmods = new HashSet<>();
|
||||||
Runtime.Version multiRelease;
|
Runtime.Version multiRelease;
|
||||||
boolean showModulesAddExports;
|
|
||||||
boolean reduced;
|
boolean hasSourcePath() {
|
||||||
|
return !addmods.isEmpty() || includePattern != null ||
|
||||||
|
includeSystemModulePattern != null;
|
||||||
|
}
|
||||||
|
|
||||||
boolean hasFilter() {
|
boolean hasFilter() {
|
||||||
return numFilters() > 0;
|
return numFilters() > 0;
|
||||||
|
@ -70,14 +70,6 @@ public class ModuleAnalyzer {
|
|||||||
public ModuleAnalyzer(JdepsConfiguration config,
|
public ModuleAnalyzer(JdepsConfiguration config,
|
||||||
PrintWriter log,
|
PrintWriter log,
|
||||||
Set<String> names) {
|
Set<String> names) {
|
||||||
|
|
||||||
if (!config.initialArchives().isEmpty()) {
|
|
||||||
String list = config.initialArchives().stream()
|
|
||||||
.map(Archive::getPathName).collect(joining(" "));
|
|
||||||
throw new JdepsTask.UncheckedBadArgs(new BadArgs("err.invalid.module.option",
|
|
||||||
list, "--check"));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.configuration = config;
|
this.configuration = config;
|
||||||
this.log = log;
|
this.log = log;
|
||||||
|
|
||||||
|
@ -151,7 +151,9 @@ main.opt.jdkinternals=\
|
|||||||
|
|
||||||
main.opt.list-deps=\
|
main.opt.list-deps=\
|
||||||
\ --list-deps Lists the dependences and use of JDK internal\n\
|
\ --list-deps Lists the dependences and use of JDK internal\n\
|
||||||
\ APIs.\n\
|
\ APIs.
|
||||||
|
|
||||||
|
main.opt.list-reduced-deps=\
|
||||||
\ --list-reduced-deps Same as --list-deps with not listing\n\
|
\ --list-reduced-deps Same as --list-deps with not listing\n\
|
||||||
\ the implied reads edges from the module graph\n\
|
\ the implied reads edges from the module graph\n\
|
||||||
\ If module M1 depends on M2 and M3,\n\
|
\ If module M1 depends on M2 and M3,\n\
|
||||||
@ -171,6 +173,7 @@ main.opt.multi-release=\
|
|||||||
\ multi-release jar files. <version> should\n\
|
\ multi-release jar files. <version> should\n\
|
||||||
\ be integer >= 9 or base.
|
\ be integer >= 9 or base.
|
||||||
|
|
||||||
|
err.command.set={0} and {1} options are specified.
|
||||||
err.unknown.option=unknown option: {0}
|
err.unknown.option=unknown option: {0}
|
||||||
err.missing.arg=no value given for {0}
|
err.missing.arg=no value given for {0}
|
||||||
err.invalid.arg.for.option=invalid argument for option: {0}
|
err.invalid.arg.for.option=invalid argument for option: {0}
|
||||||
@ -180,11 +183,10 @@ err.genmoduleinfo.unnamed.package={0} contains an unnamed package that is not al
|
|||||||
err.profiles.msg=No profile information
|
err.profiles.msg=No profile information
|
||||||
err.exception.message={0}
|
err.exception.message={0}
|
||||||
err.invalid.path=invalid path: {0}
|
err.invalid.path=invalid path: {0}
|
||||||
err.invalid.module.option=Cannot set {0} with {1} option.
|
err.invalid.options={0} cannot be used with {1} option
|
||||||
err.invalid.filters=Only one of --package (-p), --regex (-e), --require option can be set
|
|
||||||
err.module.not.found=module not found: {0}
|
err.module.not.found=module not found: {0}
|
||||||
err.root.module.not.set=root module set empty
|
err.root.module.not.set=root module set empty
|
||||||
err.invalid.inverse.option={0} cannot be used with --inverse option
|
err.filter.not.specified=--package (-p), --regex (-e), --require option must be specified
|
||||||
err.multirelease.option.exists={0} is not a multi-release jar file, but the --multi-release option is set
|
err.multirelease.option.exists={0} is not a multi-release jar file, but the --multi-release option is set
|
||||||
err.multirelease.option.notfound={0} is a multi-release jar file, but the --multi-release option is not set
|
err.multirelease.option.notfound={0} is a multi-release jar file, but the --multi-release option is not set
|
||||||
err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2}
|
err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2}
|
||||||
|
@ -136,8 +136,6 @@ public class DotFileTest {
|
|||||||
|
|
||||||
// with -P option
|
// with -P option
|
||||||
List<String> argsWithDashP = new ArrayList<>();
|
List<String> argsWithDashP = new ArrayList<>();
|
||||||
argsWithDashP.add("-dotoutput");
|
|
||||||
argsWithDashP.add(dotoutput.toString());
|
|
||||||
argsWithDashP.add("-P");
|
argsWithDashP.add("-P");
|
||||||
argsWithDashP.addAll(args);
|
argsWithDashP.addAll(args);
|
||||||
|
|
||||||
@ -162,8 +160,6 @@ public class DotFileTest {
|
|||||||
|
|
||||||
// with -P option
|
// with -P option
|
||||||
List<String> argsWithDashP = new ArrayList<>();
|
List<String> argsWithDashP = new ArrayList<>();
|
||||||
argsWithDashP.add("-dotoutput");
|
|
||||||
argsWithDashP.add(dotoutput.toString());
|
|
||||||
argsWithDashP.add("-P");
|
argsWithDashP.add("-P");
|
||||||
argsWithDashP.addAll(args);
|
argsWithDashP.addAll(args);
|
||||||
|
|
||||||
|
92
langtools/test/tools/jdeps/Options.java
Normal file
92
langtools/test/tools/jdeps/Options.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8168386
|
||||||
|
* @summary Test option validation
|
||||||
|
* @modules jdk.jdeps
|
||||||
|
* @library lib
|
||||||
|
* @build JdepsRunner
|
||||||
|
* @run testng Options
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import org.testng.annotations.DataProvider;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class Options {
|
||||||
|
private static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||||
|
|
||||||
|
@DataProvider(name = "errors")
|
||||||
|
public Object[][] errors() {
|
||||||
|
return new Object[][]{
|
||||||
|
{
|
||||||
|
new String[] { "-summary", "-v", TEST_CLASSES },
|
||||||
|
"-v, -verbose cannot be used with -s, -summary option"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new String[] { "-jdkinternal", "-summary", TEST_CLASSES },
|
||||||
|
"-summary or -verbose cannot be used with -jdkinternals option"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new String[] { "-jdkinternal", "-p", "java.lang", TEST_CLASSES },
|
||||||
|
"--package, --regex, --require cannot be used with -jdkinternals option"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new String[] { "--inverse", TEST_CLASSES },
|
||||||
|
"--package (-p), --regex (-e), --require option must be specified"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new String[] { "--inverse", "-R", TEST_CLASSES },
|
||||||
|
"-R cannot be used with --inverse option"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new String[] { "--generate-module-info", "dots", "-cp", TEST_CLASSES },
|
||||||
|
"-classpath cannot be used with --generate-module-info option"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new String[] { "--list-deps", "-summary", TEST_CLASSES },
|
||||||
|
"--list-deps and --list-reduced-deps options are specified"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
new String[] { "--list-deps", "--list-reduced-deps", TEST_CLASSES },
|
||||||
|
"--list-deps and --list-reduced-deps options are specified"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(dataProvider = "errors")
|
||||||
|
public void test(String[] options, String expected) {
|
||||||
|
jdepsError(options).outputContains(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static JdepsRunner jdepsError(String... args) {
|
||||||
|
JdepsRunner jdeps = new JdepsRunner(args);
|
||||||
|
assertTrue(jdeps.run(true) != 0);
|
||||||
|
return jdeps;
|
||||||
|
}
|
||||||
|
}
|
@ -75,7 +75,7 @@ public class JdepsRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean outputContains(String s) {
|
public boolean outputContains(String s) {
|
||||||
return stdout.toString().contains(s);
|
return stdout.toString().contains(s) || stderr.toString().contains(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printStdout(PrintStream stream) {
|
public void printStdout(PrintStream stream) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user