001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.bcel.util; 018 019import java.io.Closeable; 020import java.io.File; 021import java.io.IOException; 022import java.net.URI; 023import java.net.URL; 024import java.net.URLClassLoader; 025import java.nio.file.DirectoryStream; 026import java.nio.file.FileSystem; 027import java.nio.file.FileSystems; 028import java.nio.file.Files; 029import java.nio.file.Path; 030import java.nio.file.Paths; 031import java.util.ArrayList; 032import java.util.Collections; 033import java.util.List; 034import java.util.Map; 035 036/** 037 * Wraps a Java 9 JEP 220 modular runtime image. Requires the JRT NIO file system. 038 * 039 * @since 6.3 040 */ 041public class ModularRuntimeImage implements Closeable { 042 043 static final String MODULES_PATH = File.separator + "modules"; 044 static final String PACKAGES_PATH = File.separator + "packages"; 045 046 private final URLClassLoader classLoader; 047 private final FileSystem fileSystem; 048 049 /** 050 * Constructs a default instance. 051 */ 052 @SuppressWarnings("resource") // See #close() 053 public ModularRuntimeImage() { 054 this(null, FileSystems.getFileSystem(URI.create("jrt:/"))); 055 } 056 057 /** 058 * Constructs an instance using the JRT file system implementation from a specific Java Home. 059 * 060 * @param javaHome Path to a Java 9 or greater home. 061 * 062 * @throws IOException an I/O error occurs accessing the file system 063 */ 064 public ModularRuntimeImage(final String javaHome) throws IOException { 065 final Map<String, ?> emptyMap = Collections.emptyMap(); 066 final Path jrePath = Paths.get(javaHome); 067 final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar"); 068 this.classLoader = URLClassLoader.newInstance(new URL[] {jrtFsPath.toUri().toURL()}); 069 this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader); 070 } 071 072 private ModularRuntimeImage(final URLClassLoader cl, final FileSystem fs) { 073 this.classLoader = cl; 074 this.fileSystem = fs; 075 } 076 077 @Override 078 public void close() throws IOException { 079 if (classLoader != null) { 080 classLoader.close(); 081 } 082 if (fileSystem != null) { 083 fileSystem.close(); 084 } 085 } 086 087 public FileSystem getFileSystem() { 088 return fileSystem; 089 } 090 091 /** 092 * Lists all entries in the given directory. 093 * 094 * @param dirPath directory path. 095 * @return a list of dir entries if an I/O error occurs 096 * @throws IOException an I/O error occurs accessing the file system 097 */ 098 public List<Path> list(final Path dirPath) throws IOException { 099 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}