20
20
import java .nio .charset .StandardCharsets ;
21
21
import java .nio .file .Files ;
22
22
import java .nio .file .Path ;
23
+ import java .nio .file .Paths ;
24
+ import java .util .Arrays ;
23
25
import java .util .Collections ;
24
26
import java .util .Comparator ;
25
27
import java .util .Map ;
26
28
import java .util .Set ;
27
29
import java .util .TreeMap ;
28
30
import java .util .TreeSet ;
31
+ import java .util .function .Predicate ;
32
+ import java .util .stream .Collectors ;
29
33
import java .util .stream .Stream ;
30
34
31
35
import static org .objectweb .asm .Opcodes .ACC_DEPRECATED ;
@@ -49,15 +53,24 @@ public class JdkApiExtractor {
49
53
new AccessibleMethod ("close" , "()V" , true , false , true )
50
54
);
51
55
56
+ private static String DEPRECATIONS_ONLY = "--deprecations-only" ;
57
+ private static String INCLUDE_INCUBATOR = "--include-incubator" ;
58
+
59
+ private static Set <String > OPTIONAL_ARGS = Set .of (DEPRECATIONS_ONLY , INCLUDE_INCUBATOR );
60
+
52
61
public static void main (String [] args ) throws IOException {
53
62
validateArgs (args );
54
- boolean deprecationsOnly = args . length == 2 && args [ 1 ]. equals ( "--deprecations-only" );
63
+ boolean deprecationsOnly = optionalArgs ( args ). anyMatch ( DEPRECATIONS_ONLY :: equals );
55
64
56
65
Map <String , Set <AccessibleMethod >> accessibleImplementationsByClass = new TreeMap <>();
57
66
Map <String , Set <AccessibleMethod >> accessibleForOverridesByClass = new TreeMap <>();
58
67
Map <String , Set <AccessibleMethod >> deprecationsByClass = new TreeMap <>();
59
68
60
- Utils .walkJdkModules ((moduleName , moduleClasses , moduleExports ) -> {
69
+ Predicate <String > modulePredicate = Utils .DEFAULT_MODULE_PREDICATE .or (
70
+ m -> optionalArgs (args ).anyMatch (INCLUDE_INCUBATOR ::equals ) && m .contains (".incubator." )
71
+ );
72
+
73
+ Utils .walkJdkModules (modulePredicate , (moduleName , moduleClasses , moduleExports ) -> {
61
74
var visitor = new AccessibleClassVisitor (
62
75
moduleExports ,
63
76
accessibleImplementationsByClass ,
@@ -87,16 +100,37 @@ private static String internalClassName(Path clazz, String moduleName) {
87
100
return relativePath .substring (0 , relativePath .length () - ".class" .length ());
88
101
}
89
102
103
+ private static Stream <String > optionalArgs (String [] args ) {
104
+ return Arrays .stream (args ).skip (1 );
105
+ }
106
+
90
107
@ SuppressForbidden (reason = "cli tool printing to standard err/out" )
91
108
private static void validateArgs (String [] args ) {
92
- boolean valid = args .length == 1 || (args .length == 2 && "--deprecations-only" .equals (args [1 ]));
93
-
109
+ boolean valid = args .length > 0 && optionalArgs (args ).allMatch (OPTIONAL_ARGS ::contains );
110
+ if (valid && isWritableOutputPath (args [0 ]) == false ) {
111
+ valid = false ;
112
+ System .err .println ("invalid output path: " + args [0 ]);
113
+ }
94
114
if (valid == false ) {
95
- System .err .println ("usage: <output file path> [--deprecations-only]" );
115
+ String optionalArgs = OPTIONAL_ARGS .stream ().collect (Collectors .joining ("] [" , " [" , "]" ));
116
+ System .err .println ("usage: <output file path>" + optionalArgs );
96
117
System .exit (1 );
97
118
}
98
119
}
99
120
121
+ private static boolean isWritableOutputPath (String pathStr ) {
122
+ try {
123
+ Path path = Paths .get (pathStr );
124
+ if (Files .exists (path ) && Files .isRegularFile (path )) {
125
+ return Files .isWritable (path );
126
+ }
127
+ Path parent = path .toAbsolutePath ().getParent ();
128
+ return parent != null && Files .isDirectory (parent ) && Files .isWritable (parent );
129
+ } catch (Exception e ) {
130
+ return false ;
131
+ }
132
+ }
133
+
100
134
@ SuppressForbidden (reason = "cli tool printing to standard err/out" )
101
135
private static void writeFile (Path path , Map <String , Set <AccessibleMethod >> methods ) throws IOException {
102
136
System .out .println ("Writing result for " + Runtime .version () + " to " + path .toAbsolutePath ());
0 commit comments