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 */ 18 package org.apache.bcel.util; 19 20 import java.io.Closeable; 21 import java.io.File; 22 import java.io.IOException; 23 import java.net.URI; 24 import java.net.URL; 25 import java.net.URLClassLoader; 26 import java.nio.file.DirectoryStream; 27 import java.nio.file.FileSystem; 28 import java.nio.file.FileSystems; 29 import java.nio.file.Files; 30 import java.nio.file.Path; 31 import java.nio.file.Paths; 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.Iterator; 35 import java.util.List; 36 import java.util.Map; 37 38 /** 39 * Wraps a Java 9 JEP 220 modular runtime image. Requires the JRT NIO file system. 40 * 41 * @since 6.3 42 */ 43 public class ModularRuntimeImage implements Closeable { 44 45 static final String MODULES_PATH = File.separator + "modules"; 46 static final String PACKAGES_PATH = File.separator + "packages"; 47 48 private final URLClassLoader classLoader; 49 private final FileSystem fileSystem; 50 51 /** 52 * Constructs a default instance. 53 * 54 * @throws IOException 55 * an I/O error occurs accessing the file system 56 */ ModularRuntimeImage()57 public ModularRuntimeImage() throws IOException { 58 this(null, FileSystems.getFileSystem(URI.create("jrt:/"))); 59 } 60 61 /** 62 * Constructs an instance using the JRT file system implementation from a specific Java Home. 63 * 64 * @param javaHome 65 * Path to a Java 9 or greater home. 66 * 67 * @throws IOException 68 * an I/O error occurs accessing the file system 69 */ ModularRuntimeImage(final String javaHome)70 public ModularRuntimeImage(final String javaHome) throws IOException { 71 final Map<String, ?> emptyMap = Collections.emptyMap(); 72 final Path jrePath = Paths.get(javaHome); 73 final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar"); 74 this.classLoader = new URLClassLoader(new URL[] {jrtFsPath.toUri().toURL() }); 75 this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader); 76 } 77 ModularRuntimeImage(final URLClassLoader cl, final FileSystem fs)78 private ModularRuntimeImage(final URLClassLoader cl, final FileSystem fs) { 79 this.classLoader = cl; 80 this.fileSystem = fs; 81 } 82 83 @Override close()84 public void close() throws IOException { 85 if (classLoader != null) { 86 if (classLoader != null) { 87 classLoader.close(); 88 } 89 if (fileSystem != null) { 90 fileSystem.close(); 91 } 92 } 93 } 94 95 /** 96 * Lists all entries in the given directory. 97 * 98 * @param dirPath 99 * directory path. 100 * @return a list of dir entries if an I/O error occurs 101 * @throws IOException 102 * an I/O error occurs accessing the file system 103 */ list(final Path dirPath)104 public List<Path> list(final Path dirPath) throws IOException { 105 final List<Path> list = new ArrayList<>(); 106 try (DirectoryStream<Path> ds = Files.newDirectoryStream(dirPath)) { 107 final Iterator<Path> iterator = ds.iterator(); 108 while (iterator.hasNext()) { 109 list.add(iterator.next()); 110 } 111 } 112 return list; 113 } 114 115 /** 116 * Lists all entries in the given directory. 117 * 118 * @param dirName 119 * directory path. 120 * @return a list of dir entries if an I/O error occurs 121 * @throws IOException 122 * an I/O error occurs accessing the file system 123 */ list(final String dirName)124 public List<Path> list(final String dirName) throws IOException { 125 return list(fileSystem.getPath(dirName)); 126 } 127 128 /** 129 * Lists all modules. 130 * 131 * @return a list of modules 132 * @throws IOException 133 * an I/O error occurs accessing the file system 134 */ modules()135 public List<Path> modules() throws IOException { 136 return list(MODULES_PATH); 137 } 138 139 /** 140 * Lists all packages. 141 * 142 * @return a list of modules 143 * @throws IOException 144 * an I/O error occurs accessing the file system 145 */ packages()146 public List<Path> packages() throws IOException { 147 return list(PACKAGES_PATH); 148 } 149 getFileSystem()150 public FileSystem getFileSystem() { 151 return fileSystem; 152 } 153 154 } 155