mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-05-29 07:20:35 +00:00
Dev build fixes
This commit is contained in:
+1
-1
@@ -35,7 +35,7 @@ sdk install java 24-graalce
|
||||
sdk default java 24-graalce
|
||||
```
|
||||
.
|
||||
On Windows, you have to manually install a JDK, e.g. from [Adoptium](https://adoptium.net/temurin/releases/?version=21).
|
||||
On Windows, you have to manually install a JDK, e.g. from [Adoptium](https://adoptium.net/temurin/releases/?version=24).
|
||||
|
||||
You can configure a few development options in the file `app/dev.properties` which will be automatically generated when gradle is first run.
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.xpipe.app.ext.ProcessControlProvider;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.resources.AppResources;
|
||||
import io.xpipe.app.util.ModuleAccess;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.util.ModuleLayerLoader;
|
||||
import io.xpipe.core.util.XPipeInstallation;
|
||||
@@ -25,7 +26,7 @@ import java.util.stream.Stream;
|
||||
public class AppExtensionManager {
|
||||
|
||||
private static AppExtensionManager INSTANCE;
|
||||
private final List<Extension> loadedExtensions = new ArrayList<>();
|
||||
private final List<Module> loadedModules = new ArrayList<>();
|
||||
private final List<ModuleLayer> leafModuleLayers = new ArrayList<>();
|
||||
private final List<Path> extensionBaseDirectories = new ArrayList<>();
|
||||
private ModuleLayer baseLayer = ModuleLayer.boot();
|
||||
@@ -66,18 +67,11 @@ public class AppExtensionManager {
|
||||
throw ExtensionException.corrupt("Missing base module");
|
||||
}
|
||||
|
||||
baseLayer = baseModule.get().getModule().getLayer();
|
||||
loadedExtensions.add(baseModule.get());
|
||||
baseLayer = baseModule.get().getLayer();
|
||||
loadedModules.add(baseModule.get());
|
||||
}
|
||||
|
||||
private void determineExtensionDirectories() throws Exception {
|
||||
if (!AppProperties.get().isImage()) {
|
||||
extensionBaseDirectories.add(Path.of(System.getProperty("user.dir"))
|
||||
.resolve("app")
|
||||
.resolve("build")
|
||||
.resolve("ext_dev"));
|
||||
}
|
||||
|
||||
if (!AppProperties.get().isFullVersion()) {
|
||||
var localInstallation = XPipeInstallation.getLocalDefaultInstallationBasePath(
|
||||
AppProperties.get().isStaging() || AppProperties.get().isLocatePtb());
|
||||
@@ -104,13 +98,6 @@ public class AppExtensionManager {
|
||||
var extensions = XPipeInstallation.getLocalExtensionsDirectory(p);
|
||||
extensionBaseDirectories.add(extensions);
|
||||
}
|
||||
|
||||
var userDir = AppProperties.get().getDataDir().resolve("extensions");
|
||||
extensionBaseDirectories.add(userDir);
|
||||
|
||||
var currentInstallation = XPipeInstallation.getCurrentInstallationBasePath();
|
||||
var productionRoot = XPipeInstallation.getLocalExtensionsDirectory(currentInstallation);
|
||||
extensionBaseDirectories.add(productionRoot);
|
||||
}
|
||||
|
||||
private static String getLocalInstallVersion() throws Exception {
|
||||
@@ -126,16 +113,16 @@ public class AppExtensionManager {
|
||||
public Set<Module> getContentModules() {
|
||||
return Stream.concat(
|
||||
Stream.of(ModuleLayer.boot().findModule("io.xpipe.app").orElseThrow()),
|
||||
loadedExtensions.stream().map(extension -> extension.module))
|
||||
loadedModules.stream())
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void loadAllExtensions() {
|
||||
private void loadAllExtensions() throws Exception {
|
||||
for (var ext : List.of("system", "proc", "uacc")) {
|
||||
var extension = findAndParseExtension(ext, baseLayer)
|
||||
.orElseThrow(() -> ExtensionException.corrupt("Missing module " + ext));
|
||||
loadedExtensions.add(extension);
|
||||
leafModuleLayers.add(extension.getModule().getLayer());
|
||||
loadedModules.add(extension);
|
||||
leafModuleLayers.add(extension.getLayer());
|
||||
}
|
||||
|
||||
var scl = ClassLoader.getSystemClassLoader();
|
||||
@@ -144,13 +131,24 @@ public class AppExtensionManager {
|
||||
var cf = Configuration.resolve(finder, cfs, finder, List.of());
|
||||
extendedLayer = ModuleLayer.defineModulesWithOneLoader(cf, leafModuleLayers, scl)
|
||||
.layer();
|
||||
|
||||
if (!AppProperties.get().isFullVersion()) {
|
||||
ModuleAccess.exportAndOpen(
|
||||
ModuleLayer.boot().findModule("java.base").orElseThrow(),
|
||||
"java.io",
|
||||
extendedLayer.findModule("io.xpipe.ext.proc").orElseThrow());
|
||||
ModuleAccess.exportAndOpen(ModuleLayer.boot().findModule("org.apache.commons.io").orElseThrow(),
|
||||
"org.apache.commons.io.input",
|
||||
extendedLayer.findModule("io.xpipe.ext.proc").orElseThrow());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Optional<Extension> findAndParseExtension(String name, ModuleLayer parent) {
|
||||
private Optional<Module> findAndParseExtension(String name, ModuleLayer parent) {
|
||||
var inModulePath = ModuleLayer.boot().findModule("io.xpipe.ext." + name);
|
||||
if (inModulePath.isPresent()) {
|
||||
TrackEvent.info("Loaded extension " + name + " from boot module path");
|
||||
return Optional.of(new Extension(null, inModulePath.get().getName(), name, inModulePath.get(), 0));
|
||||
return inModulePath;
|
||||
}
|
||||
|
||||
for (Path extensionBaseDirectory : extensionBaseDirectories) {
|
||||
@@ -166,20 +164,12 @@ public class AppExtensionManager {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<Extension> parseExtensionDirectory(Path dir, ModuleLayer parent) {
|
||||
private Optional<Module> parseExtensionDirectory(Path dir, ModuleLayer parent) {
|
||||
if (!Files.exists(dir) || !Files.isDirectory(dir)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (loadedExtensions.stream().anyMatch(extension -> dir.equals(extension.dir))
|
||||
|| loadedExtensions.stream()
|
||||
.anyMatch(extension ->
|
||||
extension.id.equals(dir.getFileName().toString()))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
TrackEvent.trace(String.format("Scanning directory %s for extensions", dir));
|
||||
|
||||
try {
|
||||
ModuleFinder finder = ModuleFinder.of(dir);
|
||||
var found = finder.findAll();
|
||||
@@ -196,26 +186,8 @@ public class AppExtensionManager {
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
var layer = ModuleLayer.defineModulesWithOneLoader(cf, List.of(parent), scl)
|
||||
.layer();
|
||||
|
||||
var ext = getExtensionFromDir(layer, dir);
|
||||
if (ext.isEmpty()) {
|
||||
if (AppProperties.get().isFullVersion()) {
|
||||
throw ExtensionException.corrupt("Unable to load extension from directory " + dir);
|
||||
}
|
||||
} else {
|
||||
if (loadedExtensions.stream()
|
||||
.anyMatch(extension -> extension.getName().equals(ext.get().name))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
TrackEvent.withInfo("Loaded extension module")
|
||||
.tag("name", ext.get().getName())
|
||||
.tag("dir", dir.toString())
|
||||
.tag("dependencies", ext.get().getDependencies())
|
||||
.handle();
|
||||
|
||||
return ext;
|
||||
}
|
||||
var mod = layer.modules().iterator().next();
|
||||
return Optional.of(mod);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
ErrorEvent.fromThrowable(t)
|
||||
@@ -224,34 +196,4 @@ public class AppExtensionManager {
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<Extension> getExtensionFromDir(ModuleLayer l, Path dir) {
|
||||
return l.modules().stream()
|
||||
.map(m -> {
|
||||
AtomicReference<Extension> ext = new AtomicReference<>();
|
||||
AppResources.withResourceInLayer(m.getName(), "extension.properties", l, path -> {
|
||||
if (Files.exists(path)) {
|
||||
var props = new Properties();
|
||||
try (var in = Files.newInputStream(path)) {
|
||||
props.load(in);
|
||||
}
|
||||
var name = props.get("name").toString();
|
||||
var deps = l.modules().size() - 1;
|
||||
ext.set(new Extension(dir, dir.getFileName().toString(), name, m, deps));
|
||||
}
|
||||
});
|
||||
return Optional.ofNullable(ext.get());
|
||||
})
|
||||
.flatMap(Optional::stream)
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Value
|
||||
private static class Extension {
|
||||
Path dir;
|
||||
String id;
|
||||
String name;
|
||||
Module module;
|
||||
int dependencies;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package io.xpipe.app.util;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ModuleAccess {
|
||||
|
||||
public static void exportAndOpen(Module source, String pkg, Module target) throws Exception {
|
||||
if (source.isExported(pkg, target) && source.isOpen(pkg, target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Method getDeclaredFields0 = Class.class.getDeclaredMethod("getDeclaredMethods0", boolean.class);
|
||||
getDeclaredFields0.setAccessible(true);
|
||||
Method[] fields = (Method[]) getDeclaredFields0.invoke(Module.class, false);
|
||||
Method modifiers = null;
|
||||
for (Method each : fields) {
|
||||
if ("implAddExportsOrOpens".equals(each.getName())) {
|
||||
modifiers = each;
|
||||
break;
|
||||
}
|
||||
}
|
||||
modifiers.setAccessible(true);
|
||||
|
||||
modifiers.invoke(source, pkg, target, false, true);
|
||||
modifiers.invoke(source, pkg, target, true, true);
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -144,8 +144,7 @@ project.ext {
|
||||
|
||||
// Module access fixes
|
||||
jvmRunArgs += [
|
||||
"--add-opens", "java.base/java.io=io.xpipe.ext.proc",
|
||||
"--add-opens", "org.apache.commons.io/org.apache.commons.io.input=io.xpipe.ext.proc",
|
||||
"--add-opens", "java.base/java.lang=io.xpipe.app",
|
||||
"--add-opens", "net.synedra.validatorfx/net.synedra.validatorfx=io.xpipe.app",
|
||||
"--add-opens", "java.base/java.nio.file=io.xpipe.app",
|
||||
"--add-opens", "java.base/java.lang=io.xpipe.app",
|
||||
@@ -157,6 +156,13 @@ project.ext {
|
||||
"--add-opens", "javafx.graphics/com.sun.javafx.tk.quantum=io.xpipe.app"
|
||||
]
|
||||
|
||||
if (fullVersion) {
|
||||
jvmRunArgs += [
|
||||
"--add-opens", "java.base/java.io=io.xpipe.ext.proc",
|
||||
"--add-opens", "org.apache.commons.io/org.apache.commons.io.input=io.xpipe.ext.proc",
|
||||
]
|
||||
}
|
||||
|
||||
// Use project liliput
|
||||
jvmRunArgs += ['-XX:+UnlockExperimentalVMOptions', '-XX:+UseCompactObjectHeaders']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user