package com.github.bsideup.liiklus.plugins; import lombok.extern.slf4j.Slf4j; import org.pf4j.PluginClassLoader; import org.pf4j.PluginDescriptor; import org.pf4j.PluginLoader; import org.pf4j.PluginManager; import org.pf4j.util.FileUtils; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @Slf4j public class LiiklusPluginLoader implements PluginLoader { private final PluginManager pluginManager; public LiiklusPluginLoader(PluginManager pluginManager) { this.pluginManager = pluginManager; } @Override public boolean isApplicable(Path pluginPath) { return Files.exists(pluginPath) && FileUtils.isJarFile(pluginPath); } @Override public ClassLoader loadPlugin(Path pluginPath, PluginDescriptor pluginDescriptor) { var pluginClassLoader = new PluginClassLoader(pluginManager, pluginDescriptor, Thread.currentThread().getContextClassLoader()); pluginClassLoader.addFile(pluginPath.toFile()); // TODO consider fat jars try (var jarFileSystem = FileSystems.newFileSystem(pluginPath, null)) { var libPath = jarFileSystem.getPath("lib"); if (Files.exists(libPath)) { try (var pathStream = Files.walk(libPath, 1)) { pathStream.filter(Files::isRegularFile).forEach(it -> { try { var tempFile = Files.createTempFile(it.getFileName().toString(), ".jar"); Files.copy(it, tempFile, StandardCopyOption.REPLACE_EXISTING); pluginClassLoader.addURL(tempFile.toUri().toURL()); } catch (Exception e) { log.error("Failed to add file from {}", it.toAbsolutePath(), e); } }); } } } catch (IOException e) { throw new RuntimeException("Failed to load JARs from " + pluginPath.toAbsolutePath(), e); } return pluginClassLoader; } }