langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java
changeset 43767 9cff98a149cb
parent 42407 f3702cff2933
child 45684 2c5f2779c3d1
equal deleted inserted replaced
43648:ce7b7f98a236 43767:9cff98a149cb
    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                 }
   137 
   139 
   138     boolean notFound(Archive m) {
   140     boolean notFound(Archive m) {
   139         return m == NOT_FOUND || m == REMOVED_JDK_INTERNALS;
   141         return m == NOT_FOUND || m == REMOVED_JDK_INTERNALS;
   140     }
   142     }
   141 
   143 
   142     private Module toExplicitModule(Module module, Set<Archive> requiresTransitive)
   144     private Module toNormalModule(Module module, Set<Archive> requiresTransitive)
   143         throws IOException
   145         throws IOException
   144     {
   146     {
   145         // done analysis
   147         // done analysis
   146         module.close();
   148         module.close();
   147 
   149 
   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      */