41 import java.nio.file.Paths; |
41 import java.nio.file.Paths; |
42 import java.util.Collections; |
42 import java.util.Collections; |
43 import java.util.Comparator; |
43 import java.util.Comparator; |
44 import java.util.HashMap; |
44 import java.util.HashMap; |
45 import java.util.List; |
45 import java.util.List; |
|
46 import java.util.Locale; |
46 import java.util.Map; |
47 import java.util.Map; |
47 import java.util.Optional; |
48 import java.util.Optional; |
48 import java.util.Set; |
49 import java.util.Set; |
49 import java.util.function.Function; |
50 import java.util.function.Function; |
|
51 import java.util.stream.Collectors; |
50 import java.util.stream.Stream; |
52 import java.util.stream.Stream; |
51 import static java.util.stream.Collectors.*; |
53 import static java.util.stream.Collectors.*; |
52 |
54 |
53 |
55 |
54 public class ModuleInfoBuilder { |
56 public class ModuleInfoBuilder { |
58 |
60 |
59 final DependencyFinder dependencyFinder; |
61 final DependencyFinder dependencyFinder; |
60 final Analyzer analyzer; |
62 final Analyzer analyzer; |
61 |
63 |
62 // an input JAR file (loaded as an automatic module for analysis) |
64 // an input JAR file (loaded as an automatic module for analysis) |
63 // maps to an explicit module to generate module-info.java |
65 // maps to a normal module to generate module-info.java |
64 final Map<Module, Module> automaticToExplicitModule; |
66 final Map<Module, Module> automaticToNormalModule; |
65 public ModuleInfoBuilder(JdepsConfiguration configuration, |
67 public ModuleInfoBuilder(JdepsConfiguration configuration, |
66 List<String> args, |
68 List<String> args, |
67 Path outputdir, |
69 Path outputdir, |
68 boolean open) { |
70 boolean open) { |
69 this.configuration = configuration; |
71 this.configuration = configuration; |
76 // add targets to modulepath if it has module-info.class |
78 // add targets to modulepath if it has module-info.class |
77 List<Path> paths = args.stream() |
79 List<Path> paths = args.stream() |
78 .map(fn -> Paths.get(fn)) |
80 .map(fn -> Paths.get(fn)) |
79 .collect(toList()); |
81 .collect(toList()); |
80 |
82 |
81 // automatic module to convert to explicit module |
83 // automatic module to convert to normal module |
82 this.automaticToExplicitModule = ModuleFinder.of(paths.toArray(new Path[0])) |
84 this.automaticToNormalModule = ModuleFinder.of(paths.toArray(new Path[0])) |
83 .findAll().stream() |
85 .findAll().stream() |
84 .map(configuration::toModule) |
86 .map(configuration::toModule) |
85 .collect(toMap(Function.identity(), Function.identity())); |
87 .collect(toMap(Function.identity(), Function.identity())); |
86 |
88 |
87 Optional<Module> om = automaticToExplicitModule.keySet().stream() |
89 Optional<Module> om = automaticToNormalModule.keySet().stream() |
88 .filter(m -> !m.descriptor().isAutomatic()) |
90 .filter(m -> !m.descriptor().isAutomatic()) |
89 .findAny(); |
91 .findAny(); |
90 if (om.isPresent()) { |
92 if (om.isPresent()) { |
91 throw new UncheckedBadArgs(new BadArgs("err.genmoduleinfo.not.jarfile", |
93 throw new UncheckedBadArgs(new BadArgs("err.genmoduleinfo.not.jarfile", |
92 om.get().getPathName())); |
94 om.get().getPathName())); |
93 } |
95 } |
94 if (automaticToExplicitModule.isEmpty()) { |
96 if (automaticToNormalModule.isEmpty()) { |
95 throw new UncheckedBadArgs(new BadArgs("err.invalid.path", args)); |
97 throw new UncheckedBadArgs(new BadArgs("err.invalid.path", args)); |
96 } |
98 } |
97 } |
99 } |
98 |
100 |
99 public boolean run() throws IOException { |
101 public boolean run() throws IOException { |
113 : Collections.emptySet(); |
115 : Collections.emptySet(); |
114 |
116 |
115 Path file = outputdir.resolve(m.name()).resolve("module-info.java"); |
117 Path file = outputdir.resolve(m.name()).resolve("module-info.java"); |
116 |
118 |
117 // computes requires and requires transitive |
119 // computes requires and requires transitive |
118 Module explicitModule = toExplicitModule(m, apiDeps); |
120 Module normalModule = toNormalModule(m, apiDeps); |
119 if (explicitModule != null) { |
121 if (normalModule != null) { |
120 automaticToExplicitModule.put(m, explicitModule); |
122 automaticToNormalModule.put(m, normalModule); |
121 |
123 |
122 // generate module-info.java |
124 // generate module-info.java |
123 System.out.format("writing to %s%n", file); |
125 System.out.format("writing to %s%n", file); |
124 writeModuleInfo(file, explicitModule.descriptor()); |
126 writeModuleInfo(file, normalModule.descriptor()); |
125 } else { |
127 } else { |
126 // find missing dependences |
128 // find missing dependences |
127 System.out.format("Missing dependence: %s not generated%n", file); |
129 System.out.format("Missing dependence: %s not generated%n", file); |
128 missingDeps = true; |
130 missingDeps = true; |
129 } |
131 } |
157 |
159 |
158 analyzer.requires(module) |
160 analyzer.requires(module) |
159 .map(Archive::getModule) |
161 .map(Archive::getModule) |
160 .forEach(d -> requires.putIfAbsent(d.name(), Boolean.FALSE)); |
162 .forEach(d -> requires.putIfAbsent(d.name(), Boolean.FALSE)); |
161 |
163 |
162 return module.toStrictModule(requires); |
164 return module.toNormalModule(requires); |
163 } |
165 } |
164 |
166 |
165 /** |
167 /** |
166 * Returns the stream of resulting modules |
168 * Returns the stream of resulting modules |
167 */ |
169 */ |
168 Stream<Module> modules() { |
170 Stream<Module> modules() { |
169 return automaticToExplicitModule.values().stream(); |
171 return automaticToNormalModule.values().stream(); |
170 } |
172 } |
171 |
173 |
172 /** |
174 /** |
173 * Returns the stream of resulting ModuleDescriptors |
175 * Returns the stream of resulting ModuleDescriptors |
174 */ |
176 */ |
175 public Stream<ModuleDescriptor> descriptors() { |
177 public Stream<ModuleDescriptor> descriptors() { |
176 return automaticToExplicitModule.entrySet().stream() |
178 return automaticToNormalModule.entrySet().stream() |
177 .map(Map.Entry::getValue) |
179 .map(Map.Entry::getValue) |
178 .map(Module::descriptor); |
180 .map(Module::descriptor); |
179 } |
181 } |
180 |
182 |
181 void visitMissingDeps(Analyzer.Visitor visitor) { |
183 void visitMissingDeps(Analyzer.Visitor visitor) { |
203 Map<String, Module> modules = configuration.getModules(); |
205 Map<String, Module> modules = configuration.getModules(); |
204 // first print the JDK modules |
206 // first print the JDK modules |
205 md.requires().stream() |
207 md.requires().stream() |
206 .filter(req -> !req.name().equals("java.base")) // implicit requires |
208 .filter(req -> !req.name().equals("java.base")) // implicit requires |
207 .sorted(Comparator.comparing(Requires::name)) |
209 .sorted(Comparator.comparing(Requires::name)) |
208 .forEach(req -> writer.format(" requires %s;%n", req)); |
210 .forEach(req -> writer.format(" requires %s;%n", |
|
211 toString(req.modifiers(), req.name()))); |
209 |
212 |
210 if (!open) { |
213 if (!open) { |
211 md.exports().stream() |
214 md.exports().stream() |
212 .peek(exp -> { |
215 .peek(exp -> { |
213 if (exp.targets().size() > 0) |
216 if (exp.isQualified()) |
214 throw new InternalError(md.name() + " qualified exports: " + exp); |
217 throw new InternalError(md.name() + " qualified exports: " + exp); |
215 }) |
218 }) |
216 .sorted(Comparator.comparing(Exports::source)) |
219 .sorted(Comparator.comparing(Exports::source)) |
217 .forEach(exp -> writer.format(" exports %s;%n", exp.source())); |
220 .forEach(exp -> writer.format(" exports %s;%n", exp.source())); |
218 } |
221 } |
219 |
222 |
229 |
232 |
230 writer.println("}"); |
233 writer.println("}"); |
231 } |
234 } |
232 |
235 |
233 private Set<Module> automaticModules() { |
236 private Set<Module> automaticModules() { |
234 return automaticToExplicitModule.keySet(); |
237 return automaticToNormalModule.keySet(); |
|
238 } |
|
239 |
|
240 /** |
|
241 * Returns a string containing the given set of modifiers and label. |
|
242 */ |
|
243 private static <M> String toString(Set<M> mods, String what) { |
|
244 return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase(Locale.US)), |
|
245 Stream.of(what))) |
|
246 .collect(Collectors.joining(" ")); |
235 } |
247 } |
236 |
248 |
237 /** |
249 /** |
238 * Compute 'requires transitive' dependences by analyzing API dependencies |
250 * Compute 'requires transitive' dependences by analyzing API dependencies |
239 */ |
251 */ |