package com.oracle.svm.util;
import java.io.IOException;
import java.io.InputStream;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import jdk.internal.module.Modules;
public final class ModuleSupport {
private ModuleSupport() {
}
public static ResourceBundle getResourceBundle(String bundleName, Locale locale, ClassLoader loader) {
Class<?> bundleClass;
try {
bundleClass = loader.loadClass(bundleName);
} catch (ClassNotFoundException ex) {
return getResourceBundleFallback(bundleName, locale, loader);
}
ModuleSupport.openModule(bundleClass, ModuleSupport.class);
return ResourceBundle.getBundle(bundleName, locale, bundleClass.getModule());
}
private static ResourceBundle getResourceBundleFallback(String bundleName, Locale locale, ClassLoader loader) {
for (Module module : ModuleLayer.boot().modules()) {
try {
return ResourceBundle.getBundle(bundleName, locale, module);
} catch (MissingResourceException e2) {
}
}
return ResourceBundle.getBundle(bundleName, locale, loader);
}
public static boolean hasSystemModule(String moduleName) {
return ModuleFinder.ofSystem().find(moduleName).isPresent();
}
public static List<String> getModuleResources(Collection<Path> modulePath) {
ArrayList<String> result = new ArrayList<>();
for (ModuleReference moduleReference : ModuleFinder.of(modulePath.toArray(Path[]::new)).findAll()) {
try (ModuleReader moduleReader = moduleReference.open()) {
result.addAll(moduleReader.list().collect(Collectors.toList()));
} catch (IOException e) {
throw new RuntimeException("Unable get list of resources in module" + moduleReference.descriptor().name(), e);
}
}
return result;
}
public static List<String> getSystemModuleResources(Collection<String> names) {
List<String> result = new ArrayList<>();
for (String name : names) {
Optional<ModuleReference> moduleReference = ModuleFinder.ofSystem().find(name);
if (moduleReference.isEmpty()) {
throw new RuntimeException("Unable find ModuleReference for module " + name);
}
try (ModuleReader moduleReader = moduleReference.get().open()) {
result.addAll(moduleReader.list().collect(Collectors.toList()));
} catch (IOException e) {
throw new RuntimeException("Unable get list of resources in module" + name, e);
}
}
return result;
}
public static void openModule(Class<?> declaringClass, Class<?> accessingClass) {
Module declaringModule = declaringClass.getModule();
String packageName = declaringClass.getPackageName();
Module accessingModule = accessingClass == null ? null : accessingClass.getModule();
if (accessingModule != null && accessingModule.isNamed()) {
if (!declaringModule.isOpen(packageName, accessingModule)) {
Modules.addOpens(declaringModule, packageName, accessingModule);
}
} else {
Modules.addOpensToAllUnnamed(declaringModule, packageName);
}
}
public static ClassLoader getPlatformClassLoader() {
return ClassLoader.getPlatformClassLoader();
}
@SuppressWarnings("unused")
public static void exportAndOpenAllPackagesToUnnamed(String name, boolean optional) {
Optional<Module> value = ModuleLayer.boot().findModule(name);
if (value.isEmpty()) {
if (!optional) {
throw new NoSuchElementException("No module in boot layer named " + name + ". Available modules: " + ModuleLayer.boot());
}
return;
}
Module module = value.get();
Set<String> packages = module.getPackages();
for (String pkg : packages) {
Modules.addExportsToAllUnnamed(module, pkg);
Modules.addOpensToAllUnnamed(module, pkg);
}
}
@SuppressWarnings("unused")
public static void exportAndOpenPackageToUnnamed(String name, String pkg, boolean optional) {
Optional<Module> value = ModuleLayer.boot().findModule(name);
if (value.isEmpty()) {
if (!optional) {
throw new NoSuchElementException(name);
}
return;
}
Module module = value.get();
Modules.addExportsToAllUnnamed(module, pkg);
Modules.addOpensToAllUnnamed(module, pkg);
}
public static String getModuleName(Class<?> clazz) {
return clazz.getModule().getName();
}
@SuppressWarnings("unused")
public static void findResourcesInModules(Predicate<String> resourceNameFilter, BiConsumer<String, InputStream> operation) throws IOException {
for (ResolvedModule resolvedModule : ModuleLayer.boot().configuration().modules()) {
ModuleReference modRef = resolvedModule.reference();
try (ModuleReader moduleReader = modRef.open()) {
final List<String> resources = moduleReader.list()
.filter(resourceNameFilter)
.collect(Collectors.toList());
for (String resName : resources) {
Optional<InputStream> content = moduleReader.open(resName);
if (content.isEmpty()) {
continue;
}
InputStream is = content.get();
operation.accept(resName, is);
is.close();
}
}
}
}
}