ModularRuntimeImage.java

  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. import java.io.Closeable;
  19. import java.io.File;
  20. import java.io.IOException;
  21. import java.net.URI;
  22. import java.net.URL;
  23. import java.net.URLClassLoader;
  24. import java.nio.file.DirectoryStream;
  25. import java.nio.file.FileSystem;
  26. import java.nio.file.FileSystems;
  27. import java.nio.file.Files;
  28. import java.nio.file.Path;
  29. import java.nio.file.Paths;
  30. import java.util.ArrayList;
  31. import java.util.Collections;
  32. import java.util.List;
  33. import java.util.Map;

  34. /**
  35.  * Wraps a Java 9 JEP 220 modular runtime image. Requires the JRT NIO file system.
  36.  *
  37.  * @since 6.3
  38.  */
  39. public class ModularRuntimeImage implements Closeable {

  40.     static final String MODULES_PATH = File.separator + "modules";
  41.     static final String PACKAGES_PATH = File.separator + "packages";

  42.     private final URLClassLoader classLoader;
  43.     private final FileSystem fileSystem;

  44.     /**
  45.      * Constructs a default instance.
  46.      */
  47.     @SuppressWarnings("resource") // See #close()
  48.     public ModularRuntimeImage() {
  49.         this(null, FileSystems.getFileSystem(URI.create("jrt:/")));
  50.     }

  51.     /**
  52.      * Constructs an instance using the JRT file system implementation from a specific Java Home.
  53.      *
  54.      * @param javaHome Path to a Java 9 or greater home.
  55.      *
  56.      * @throws IOException an I/O error occurs accessing the file system
  57.      */
  58.     public ModularRuntimeImage(final String javaHome) throws IOException {
  59.         final Map<String, ?> emptyMap = Collections.emptyMap();
  60.         final Path jrePath = Paths.get(javaHome);
  61.         final Path jrtFsPath = jrePath.resolve("lib").resolve("jrt-fs.jar");
  62.         this.classLoader = URLClassLoader.newInstance(new URL[] {jrtFsPath.toUri().toURL()});
  63.         this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), emptyMap, classLoader);
  64.     }

  65.     private ModularRuntimeImage(final URLClassLoader cl, final FileSystem fs) {
  66.         this.classLoader = cl;
  67.         this.fileSystem = fs;
  68.     }

  69.     @Override
  70.     public void close() throws IOException {
  71.         if (classLoader != null) {
  72.             classLoader.close();
  73.         }
  74.         if (fileSystem != null) {
  75.             fileSystem.close();
  76.         }
  77.     }

  78.     public FileSystem getFileSystem() {
  79.         return fileSystem;
  80.     }

  81.     /**
  82.      * Lists all entries in the given directory.
  83.      *
  84.      * @param dirPath directory path.
  85.      * @return a list of dir entries if an I/O error occurs
  86.      * @throws IOException an I/O error occurs accessing the file system
  87.      */
  88.     public List<Path> list(final Path dirPath) throws IOException {
  89.         final List<Path> list = new ArrayList<>();
  90.         try (DirectoryStream<Path> ds = Files.newDirectoryStream(dirPath)) {
  91.             ds.forEach(list::add);
  92.         }
  93.         return list;
  94.     }

  95.     /**
  96.      * Lists all entries in the given directory.
  97.      *
  98.      * @param dirName directory path.
  99.      * @return a list of dir entries if an I/O error occurs
  100.      * @throws IOException an I/O error occurs accessing the file system
  101.      */
  102.     public List<Path> list(final String dirName) throws IOException {
  103.         return list(fileSystem.getPath(dirName));
  104.     }

  105.     /**
  106.      * Lists all modules.
  107.      *
  108.      * @return a list of modules
  109.      * @throws IOException an I/O error occurs accessing the file system
  110.      */
  111.     public List<Path> modules() throws IOException {
  112.         return list(MODULES_PATH);
  113.     }

  114.     /**
  115.      * Lists all packages.
  116.      *
  117.      * @return a list of modules
  118.      * @throws IOException an I/O error occurs accessing the file system
  119.      */
  120.     public List<Path> packages() throws IOException {
  121.         return list(PACKAGES_PATH);
  122.     }

  123. }