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 * 017 */ 018package org.apache.bcel.util; 019 020import java.io.Closeable; 021import java.io.File; 022import java.io.IOException; 023import java.net.URI; 024import java.net.URL; 025import java.net.URLClassLoader; 026import java.nio.file.DirectoryStream; 027import java.nio.file.FileSystem; 028import java.nio.file.FileSystems; 029import java.nio.file.Files; 030import java.nio.file.Path; 031import java.nio.file.Paths; 032import java.util.ArrayList; 033import java.util.Collections; 034import java.util.Iterator; 035import java.util.List; 036import java.util.Map; 037 038/** 039 * Wraps a Java 9 JEP 220 modular runtime image. Requires the JRT NIO file system. 040 * 041 * @since 6.3 042 */ 043public class ModularRuntimeImage implements Closeable { 044 045 static final String MODULES_PATH = File.separator + "modules"; 046 static final String PACKAGES_PATH = File.separator + "packages"; 047 048 private final URLClassLoader classLoader; 049 private final FileSystem fileSystem; 050 051 /** 052 * Constructs a default instance. 053 * 054 * @throws IOException 055 * an I/O error occurs accessing the file system 056 */ 057 public ModularRuntimeImage() throws IOException { 058 this(null, FileSystems.getFileSystem(URI.create("jrt:/"))); 059 } 060 061 /** 062 * Constructs an instance using the JRT file system implementation from a specific Java Home. 063 * 064 * @param javaHome 065 * Path to a Java 9 or greater home. 066 * 067 * @throws IOException 068 * an I/O error occurs accessing the file system 069 */ 070 public ModularRuntimeImage(final String javaHome) throws IOException { 071 final Map<String, ?> emptyMap = Collections.emptyMap(); 072 final Path jrePath = Paths.get(javaHome); 073 final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar"); 074 this.classLoader = new URLClassLoader(new URL[] {jrtFsPath.toUri().toURL() }); 075 this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader); 076 } 077 078 private ModularRuntimeImage(final URLClassLoader cl, final FileSystem fs) { 079 this.classLoader = cl; 080 this.fileSystem = fs; 081 } 082 083 @Override 084 public void close() throws IOException { 085 if (classLoader != null) { 086 if (classLoader != null) { 087 classLoader.close(); 088 } 089 if (fileSystem != null) { 090 fileSystem.close(); 091 } 092 } 093 } 094 095 /** 096 * Lists all entries in the given directory. 097 * 098 * @param dirPath 099 * 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 */ 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 */ 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 */ 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 */ 146 public List<Path> packages() throws IOException { 147 return list(PACKAGES_PATH); 148 } 149 150 public FileSystem getFileSystem() { 151 return fileSystem; 152 } 153 154}