View Javadoc
1   package org.codehaus.plexus.languages.java.jpms;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.nio.file.Files;
25  import java.nio.file.Path;
26  import java.util.jar.JarEntry;
27  import java.util.jar.JarFile;
28  import java.util.jar.Manifest;
29  
30  import org.codehaus.plexus.languages.java.version.JavaVersion;
31  
32  abstract class AbstractBinaryModuleInfoParser implements ModuleInfoParser {
33      @Override
34      public JavaModuleDescriptor getModuleDescriptor(Path modulePath) throws IOException {
35          return getModuleDescriptor(modulePath, JavaVersion.JAVA_SPECIFICATION_VERSION);
36      }
37  
38      @Override
39      public JavaModuleDescriptor getModuleDescriptor(Path modulePath, JavaVersion jdkVersion) throws IOException {
40          JavaModuleDescriptor descriptor;
41          if (Files.isDirectory(modulePath)) {
42              try (InputStream in = Files.newInputStream(modulePath.resolve("module-info.class"))) {
43                  descriptor = parse(in);
44              }
45          } else {
46              try (JarFile jarFile = new JarFile(modulePath.toFile())) {
47                  JarEntry moduleInfo;
48                  if (modulePath.toString().toLowerCase().endsWith(".jmod")) {
49                      moduleInfo = jarFile.getJarEntry("classes/module-info.class");
50                  } else {
51                      moduleInfo = jarFile.getJarEntry("module-info.class");
52  
53                      if (moduleInfo == null) {
54                          Manifest manifest = jarFile.getManifest();
55  
56                          if (manifest != null
57                                  && "true"
58                                          .equalsIgnoreCase(
59                                                  manifest.getMainAttributes().getValue("Multi-Release"))) {
60                              int javaVersion =
61                                      Integer.valueOf(jdkVersion.asMajor().getValue(1));
62  
63                              for (int version = javaVersion; version >= 9; version--) {
64                                  String resource = "META-INF/versions/" + version + "/module-info.class";
65                                  JarEntry entry = jarFile.getJarEntry(resource);
66                                  if (entry != null) {
67                                      moduleInfo = entry;
68                                      break;
69                                  }
70                              }
71                          }
72                      }
73                  }
74  
75                  if (moduleInfo != null) {
76                      descriptor = parse(jarFile.getInputStream(moduleInfo));
77                  } else {
78                      descriptor = null;
79                  }
80              }
81          }
82          return descriptor;
83      }
84  
85      abstract JavaModuleDescriptor parse(InputStream in) throws IOException;
86  }