View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.bcel.util;
18  
19  import java.io.Closeable;
20  import java.io.File;
21  import java.io.IOException;
22  import java.net.URI;
23  import java.net.URL;
24  import java.net.URLClassLoader;
25  import java.nio.file.DirectoryStream;
26  import java.nio.file.FileSystem;
27  import java.nio.file.FileSystems;
28  import java.nio.file.Files;
29  import java.nio.file.Path;
30  import java.nio.file.Paths;
31  import java.util.ArrayList;
32  import java.util.Collections;
33  import java.util.List;
34  import java.util.Map;
35  
36  /**
37   * Wraps a Java 9 JEP 220 modular runtime image. Requires the JRT NIO file system.
38   *
39   * @since 6.3
40   */
41  public class ModularRuntimeImage implements Closeable {
42  
43      static final String MODULES_PATH = File.separator + "modules";
44      static final String PACKAGES_PATH = File.separator + "packages";
45  
46      private final URLClassLoader classLoader;
47      private final FileSystem fileSystem;
48  
49      /**
50       * Constructs a default instance.
51       */
52      @SuppressWarnings("resource") // See #close()
53      public ModularRuntimeImage() {
54          this(null, FileSystems.getFileSystem(URI.create("jrt:/")));
55      }
56  
57      /**
58       * Constructs an instance using the JRT file system implementation from a specific Java Home.
59       *
60       * @param javaHome Path to a Java 9 or greater home.
61       *
62       * @throws IOException an I/O error occurs accessing the file system
63       */
64      public ModularRuntimeImage(final String javaHome) throws IOException {
65          final Map<String, ?> emptyMap = Collections.emptyMap();
66          final Path jrePath = Paths.get(javaHome);
67          final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar");
68          this.classLoader = URLClassLoader.newInstance(new URL[] {jrtFsPath.toUri().toURL()});
69          this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader);
70      }
71  
72      private ModularRuntimeImage(final URLClassLoader cl, final FileSystem fs) {
73          this.classLoader = cl;
74          this.fileSystem = fs;
75      }
76  
77      @Override
78      public void close() throws IOException {
79          if (classLoader != null) {
80              classLoader.close();
81          }
82          if (fileSystem != null) {
83              fileSystem.close();
84          }
85      }
86  
87      public FileSystem getFileSystem() {
88          return fileSystem;
89      }
90  
91      /**
92       * Lists all entries in the given directory.
93       *
94       * @param dirPath directory path.
95       * @return a list of dir entries if an I/O error occurs
96       * @throws IOException an I/O error occurs accessing the file system
97       */
98      public List<Path> list(final Path dirPath) throws IOException {
99          final List<Path> list = new ArrayList<>();
100         try (DirectoryStream<Path> ds = Files.newDirectoryStream(dirPath)) {
101             ds.forEach(list::add);
102         }
103         return list;
104     }
105 
106     /**
107      * Lists all entries in the given directory.
108      *
109      * @param dirName directory path.
110      * @return a list of dir entries if an I/O error occurs
111      * @throws IOException an I/O error occurs accessing the file system
112      */
113     public List<Path> list(final String dirName) throws IOException {
114         return list(fileSystem.getPath(dirName));
115     }
116 
117     /**
118      * Lists all modules.
119      *
120      * @return a list of modules
121      * @throws IOException an I/O error occurs accessing the file system
122      */
123     public List<Path> modules() throws IOException {
124         return list(MODULES_PATH);
125     }
126 
127     /**
128      * Lists all packages.
129      *
130      * @return a list of modules
131      * @throws IOException an I/O error occurs accessing the file system
132      */
133     public List<Path> packages() throws IOException {
134         return list(PACKAGES_PATH);
135     }
136 
137 }