2
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
26
* @bug 8015912 8029216 8048063 8050804
27
* @summary Test -apionly and -jdkinternals options
29
* @modules java.base/sun.security.x509
31
* jdk.jdeps/com.sun.tools.jdeps
36
import java.io.IOException;
37
import java.io.PrintWriter;
38
import java.io.StringWriter;
39
import java.nio.file.*;
41
import java.util.regex.*;
42
import java.util.stream.Collectors;
45
public static void main(String... args) throws Exception {
47
errors += new APIDeps().run();
49
throw new Exception(errors + " errors found");
52
private static final Path dest = Paths.get(System.getProperty("test.classes", "."), "tmp");
53
private static final String[] srcDirs = new String[] {
54
"m", "b", "c", "d", "e", "f", "g"
56
void setup(Path dest) throws IOException {
57
CompilerUtils.cleanDir(dest);
58
Files.createDirectories(dest);
59
Path testsrc = Paths.get(System.getProperty("test.src"));
60
List<String> options = new ArrayList<>();
62
// jdk.jdeps is a service provider module so needs to be explicitly included
63
options.add("--add-modules=jdk.jdeps");
66
String testModules = System.getProperty("test.modules", "");
67
List<String> addExports = new ArrayList<>();
68
for (String s : testModules.split("\\s+")) {
69
if (s.isEmpty()) continue;
70
if (s.indexOf('/') != -1)
71
addExports.add("--add-exports=" + s.trim() + "=ALL-UNNAMED");
73
options.addAll(addExports);
75
for (String dir : srcDirs) {
76
Path source = testsrc.resolve(dir);
77
boolean ok = CompilerUtils.compile(source, dest, options.toArray(new String[0]));
79
throw new RuntimeException("compilation fails");
84
int run() throws IOException {
85
// compile classes in a separate directory for analysis
88
File testDir = dest.toFile();
89
String testDirBasename = testDir.toPath().getFileName().toString();
90
File mDir = new File(testDir, "m");
92
test(new File(mDir, "Bar.class"),
93
new String[] {"java.lang.Object", "java.lang.String",
94
"java.util.Set", "java.util.HashSet",
95
"java.lang.management.ManagementFactory",
96
"java.lang.management.RuntimeMXBean",
97
"b.B", "c.C", "d.D", "f.F", "g.G"},
98
new String[] {"-classpath", testDir.getPath(), "-verbose"});
99
test(new File(mDir, "Foo.class"),
100
new String[] {"c.I", "e.E", "f.F"},
101
new String[] {"-classpath", testDir.getPath(), "-verbose:class"});
102
test(new File(mDir, "Foo.class"),
103
new String[] {"c.I", "e.E", "f.F", "m.Bar"},
104
new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-filter:none"});
105
test(new File(mDir, "Gee.class"),
106
new String[] {"g.G", "sun.security.x509.X509CertInfo", "com.sun.tools.jdeps.Analyzer",
107
"com.sun.management.ThreadMXBean", "com.sun.source.tree.BinaryTree"},
108
new String[] {"-classpath", testDir.getPath(), "-verbose"});
111
test(new File(mDir, "Gee.class"),
112
new String[] {"sun.security.x509.X509CertInfo", "com.sun.tools.jdeps.Analyzer"},
113
new String[] {"-jdkinternals", "-quiet"});
114
// -jdkinternals parses all classes on -classpath and the input arguments
115
test(new File(mDir, "Gee.class"),
116
new String[] {"com.sun.tools.jdeps.Analyzer",
117
"sun.security.x509.X509CertInfo"},
118
// use -classpath tmp/a with no use of JDK internal API
119
new String[] {"-classpath", dest.resolve("a").toString(), "-jdkinternals", "-quiet"});
123
new String[] {"java.lang.Object", "java.lang.String",
125
"c.C", "d.D", "c.I", "e.E"},
126
new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-apionly"});
129
new String[] {"java.lang.Object", "java.lang.String",
131
"c.C", "d.D", "c.I", "e.E", "m.Bar"},
132
new String[] {"-classpath", testDir.getPath(), "-verbose", "--api-only"});
136
void test(File file, String[] expect) {
137
test(file, expect, new String[0]);
140
void test(File file, String[] expect, String[] options) {
141
List<String> args = new ArrayList<>(Arrays.asList(options));
143
args.add(file.getPath());
145
checkResult("api-dependencies", expect,
146
jdeps(args.toArray(new String[0])).keySet());
149
Map<String,String> jdeps(String... args) {
150
StringWriter sw = new StringWriter();
151
PrintWriter pw = new PrintWriter(sw);
152
System.err.println("jdeps " + Arrays.stream(args)
153
.collect(Collectors.joining(" ")));
154
int rc = com.sun.tools.jdeps.Main.run(args, pw);
156
String out = sw.toString();
158
System.err.println(out);
160
throw new Error("jdeps failed: rc=" + rc);
161
return findDeps(out);
164
// Pattern used to parse lines
165
private static Pattern linePattern = Pattern.compile(".*\r?\n");
166
private static Pattern pattern = Pattern.compile("\\s+ -> (\\S+) +(.*)");
168
// Use the linePattern to break the given String into lines, applying
169
// the pattern to each line to see if we have a match
170
private static Map<String,String> findDeps(String out) {
171
Map<String,String> result = new HashMap<>();
172
Matcher lm = linePattern.matcher(out); // Line matcher
173
Matcher pm = null; // Pattern matcher
177
CharSequence cs = lm.group(); // The current line
179
pm = pattern.matcher(cs);
183
result.put(pm.group(1), pm.group(2).trim());
184
if (lm.end() == out.length())
190
void checkResult(String label, String[] expect, Collection<String> found) {
191
// check the dependencies
192
if (!isEqual(expect, found)) {
193
error("Unexpected " + label + " found: '" + found +
194
"', expected: '" + Arrays.toString(expect) + "'");
198
boolean isEqual(String[] expected, Collection<String> found) {
199
if (expected.length != found.size())
202
List<String> list = new ArrayList<>(found);
203
list.removeAll(Arrays.asList(expected));
204
return list.isEmpty();
207
void error(String msg) {
208
System.err.println("Error: " + msg);