Attempt to fix 3

This commit is contained in:
Johannes Frohnmeyer 2022-09-06 14:55:36 +02:00
parent 3dd66de0a7
commit ad18164d69
Signed by: Johannes
GPG Key ID: E76429612C2929F4
12 changed files with 71 additions and 96 deletions

View File

@ -2,9 +2,6 @@ package io.gitlab.jfronny.inceptum.common;
import io.gitlab.jfronny.commons.OSUtils;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.*;
public class MetaHolder {
@ -12,12 +9,12 @@ public class MetaHolder {
static {
if (System.getProperty("inceptum.base") == null) {
Path runDir = getRunDir();
BASE_PATH = (BuildMetadata.IS_RELEASE && !Files.exists(runDir)
? getConfigPath().resolve("Inceptum")
: runDir).toAbsolutePath();
Path runDir = Path.of(".").resolve("run").toAbsolutePath();
if (!BuildMetadata.IS_RELEASE) BASE_PATH = runDir;
else if (Files.exists(runDir)) BASE_PATH = runDir;
else BASE_PATH = getConfigPath().resolve("Inceptum");
} else {
BASE_PATH = Paths.get(System.getProperty("inceptum.base")).toAbsolutePath();
BASE_PATH = getPath(System.getProperty("inceptum.base"));
}
}
@ -30,38 +27,24 @@ public class MetaHolder {
public static final Path ASSETS_DIR = BASE_PATH.resolve("assets");
public static final Path INSTANCE_DIR = BASE_PATH.resolve("instances");
public static final Path CACHE_DIR = BASE_PATH.resolve("cache");
private static boolean isWrapper = false; //TODO move to build-time argument and download correct file in wrapper
private static boolean isWrapper = false;
private static Path getConfigPath() {
return switch (OSUtils.TYPE) {
case WINDOWS -> Paths.get(System.getenv("APPDATA"));
case MAC_OS -> Paths.get(System.getProperty("user.home")).resolve("Library").resolve("Application Support");
case WINDOWS -> getPath(System.getenv("APPDATA"));
case MAC_OS -> getPath(System.getProperty("user.home")).resolve("Library").resolve("Application Support");
case LINUX -> {
String s = System.getenv().get("XDG_CONFIG_HOME");
if (s == null)
yield Paths.get(System.getProperty("user.home")).resolve(".config");
yield getPath(System.getProperty("user.home")).resolve(".config");
else
yield Paths.get(s);
yield getPath(s);
}
};
}
private static Path getRunDir() {
Path simpleRunDir = Path.of(".").resolve("run");
if (Files.exists(simpleRunDir)) return simpleRunDir;
URL url = MetaHolder.class.getProtectionDomain().getCodeSource().getLocation();
String p = url.getPath();
if (p.endsWith(".jar") && !p.endsWith("/build/libs/wrapper-" + BuildMetadata.VERSION + ".jar")) {
try {
return new File(url.toURI()).toPath().getParent().resolve("run");
} catch (URISyntaxException e) {
Utils.LOGGER.error("Could not resolve dev env run dir");
return simpleRunDir;
}
} else {
System.out.println("Not running in a jar, using ./run");
return simpleRunDir;
}
private static Path getPath(String text) {
return Paths.get(text).toAbsolutePath();
}
public static void setWrapperFlag() {

View File

@ -49,8 +49,10 @@ public class Utils {
return JFiles.openZipFile(zip, create, SYSTEM_LOADER);
}
public static void setSystemLoader(ClassLoader loader) {
@SuppressWarnings("unused") // Called through reflection from wrapper
public static void wrapperInit(ClassLoader loader) {
SYSTEM_LOADER = loader;
MetaHolder.setWrapperFlag();
}
/**

View File

@ -15,8 +15,7 @@ public class CliMain {
new ModCommand(),
new ExportCommand(),
new JvmStateCommand(),
new BatchCommand(),
new WrapperCommand() //TODO remove once wrapper is a build flag
new BatchCommand()
));
public static final Command COMMANDS_ROOT = new Command("Root command", "<command>", List.of(), KNOWN_COMMANDS) {
@ -32,14 +31,14 @@ public class CliMain {
}
};
public static CommandResolution resolve(String[] args, boolean wrapped) {
return COMMANDS_ROOT.resolve(new CommandArgs(Arrays.asList(args), wrapped));
public static CommandResolution resolve(String[] args) {
return COMMANDS_ROOT.resolve(new CommandArgs(Arrays.asList(args)));
}
public static void main(String[] args) throws Exception {
LauncherEnv.checkClassLoaderState();
CommandResolution command = resolve(args, false);
CommandResolution command = resolve(args);
if (command.command().enableLog()) {
Utils.LOGGER.info("Launching Inceptum v" + BuildMetadata.VERSION);
Utils.LOGGER.info("Loading from " + MetaHolder.BASE_PATH);

View File

@ -5,12 +5,10 @@ import java.util.*;
public class CommandArgs implements Iterable<String> {
protected final List<String> args;
public final int length;
public final boolean wrapped;
public CommandArgs(List<String> args, boolean wrapped) {
public CommandArgs(List<String> args) {
this.args = List.copyOf(args);
this.length = args.size();
this.wrapped = wrapped;
}
public boolean contains(String param) {
@ -50,11 +48,7 @@ public class CommandArgs implements Iterable<String> {
}
public CommandArgs subArgs() {
return subArgs(wrapped);
}
public CommandArgs subArgs(boolean wrapped) {
return new CommandArgs(args.subList(1, args.size()), wrapped);
return new CommandArgs(args.subList(1, args.size()));
}
@Override

View File

@ -21,7 +21,7 @@ public class HelpCommand extends Command {
CommandResolution resolution = CliMain.COMMANDS_ROOT.resolve(args);
if (resolution.resolvePath().isEmpty()) {
System.err.println("Could not find command matching your input");
invoke(new CommandArgs(List.of(), args.wrapped));
invoke(new CommandArgs(List.of()));
return;
}
printHeader();

View File

@ -1,28 +0,0 @@
package io.gitlab.jfronny.inceptum.cli.commands;
import io.gitlab.jfronny.inceptum.cli.*;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
public class WrapperCommand extends Command {
public WrapperCommand() {
super("Invokes a command in a wrapper environment", "<command>", "wrapper");
}
@Override
protected void invoke(CommandArgs args) {
throw new RuntimeException("Attempted to invoke wrapper command. This should not happen");
}
@Override
public CommandResolution resolve(CommandArgs args) {
if (MetaHolder.isWrapper()) {
throw new IllegalStateException("The WrapperStrap classloader does not match the inceptum loader. Are you using the latest wrapper?");
}
return CliMain.COMMANDS_ROOT.resolve(args);
}
@Override
public void buildHelp(HelpBuilder builder) {
// Don't show this in help
}
}

View File

@ -11,7 +11,7 @@ public class GuiCommand extends Command {
@Override
public void invoke(CommandArgs args) {
GuiMain.main(args.wrapped);
GuiMain.main();
}
@Override

View File

@ -26,7 +26,7 @@ public class UpdateCheckCommand extends Command {
@Override
protected void invoke(CommandArgs args) {
if (install && !args.wrapped) {
if (install && !MetaHolder.isWrapper()) {
Utils.LOGGER.error("Automatic updates are not supported without the wrapper");
return;
}

View File

@ -44,13 +44,13 @@ public class GuiMain {
Utils.LOGGER.info("Loading from " + MetaHolder.BASE_PATH);
LauncherEnv.initialize(new GuiEnvBackend());
try {
main(false);
main();
} finally {
LauncherEnv.terminate();
}
}
public static void main(boolean wrapped) {
public static void main() {
UpdateMetadata update = BuildMetadata.IS_PUBLIC ? Updater.getUpdate() : null;
AccountManager.loadAccounts();
Utils.LOGGER.info("Initializing UI");
@ -65,7 +65,7 @@ public class GuiMain {
init();
if (update == null) {
WINDOWS.add(new MainWindow());
} else if (wrapped) {
} else if (MetaHolder.isWrapper()) {
LauncherEnv.showOkCancel("An update was found. Should it be installed automatically?", "Update found", () -> {
try {
Updater.update(update, true);

View File

@ -15,8 +15,6 @@ import java.util.stream.Collectors;
public class Wrapper {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, URISyntaxException {
Utils.setSystemLoader(WrapperStrap.SYSTEM_LOADER);
MetaHolder.setWrapperFlag();
System.out.println("Inceptum Wrapper v" + BuildMetadata.VERSION);
System.out.println("Loading from " + MetaHolder.BASE_PATH);
InceptumEnvironmentInitializer.initialize();
@ -24,13 +22,10 @@ public class Wrapper {
if (!BuildMetadata.IS_RELEASE) {
System.out.println("Using classpath: " + classpath.stream().map(Path::toString).collect(Collectors.joining("" + File.pathSeparator)));
}
String[] newArgs = new String[args.length + 1];
newArgs[0] = "wrapper";
System.arraycopy(args, 0, newArgs, 1, args.length);
System.out.println("Starting Inceptum ClassLoader");
WrapperStrap.bootstrap(classpath,
"io.gitlab.jfronny.inceptum.Inceptum",
newArgs);
args);
}
private static List<Path> getClasspath() throws IOException, URISyntaxException {

View File

@ -1,6 +1,6 @@
package io.gitlab.jfronny.inceptum;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.commons.io.JFiles;
import org.jetbrains.annotations.Nullable;
import java.io.Closeable;
@ -8,18 +8,25 @@ import java.io.IOException;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.Stream;
public class WrapperClassLoader extends ClassLoader implements Closeable {
private final Set<Path> sources = new LinkedHashSet<>();
private final Set<Closeable> closeables = new HashSet<>();
private final ClassLoader parent;
public WrapperClassLoader(Iterable<Path> jars) throws IOException, URISyntaxException {
static {
registerAsParallelCapable();
}
public WrapperClassLoader(Iterable<Path> jars, ClassLoader parent) throws IOException, URISyntaxException {
super(null);
this.parent = parent;
for (Path jar : jars) {
if (Files.isDirectory(jar)) {
sources.add(jar);
} else {
FileSystem fs = Utils.openZipFile(jar, false);
FileSystem fs = JFiles.openZipFile(jar, false, parent);
closeables.add(fs);
sources.add(fs.getPath(""));
}
@ -29,7 +36,7 @@ public class WrapperClassLoader extends ClassLoader implements Closeable {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Path path = findClassSource(name);
if (path == null) return WrapperStrap.SYSTEM_LOADER.loadClass(name);
if (path == null) return parent.loadClass(name);
byte[] clazz;
try {
clazz = Files.readAllBytes(path);
@ -42,7 +49,7 @@ public class WrapperClassLoader extends ClassLoader implements Closeable {
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if (findClassSource(name) == null || name.equals("io.gitlab.jfronny.inceptum.WrapperStrap"))
return WrapperStrap.SYSTEM_LOADER.loadClass(name);
return parent.loadClass(name);
synchronized (this.getClassLoadingLock(name)) {
Class<?> c = this.findLoadedClass(name);
if (c == null) c = this.findClass(name);
@ -54,9 +61,20 @@ public class WrapperClassLoader extends ClassLoader implements Closeable {
@Override
public URL getResource(String name) {
Path p = findSource(name);
if (p == null) return WrapperStrap.SYSTEM_LOADER.getResource(name);
if (p == null) return parent.getResource(name);
return toUrl(p);
}
@Override
protected Enumeration<URL> findResources(String name) {
Stream<URL> resources = findPaths(name).map(this::toUrl);
resources = Stream.concat(resources, parent.resources(name));
return Collections.enumeration(resources.toList());
}
private URL toUrl(Path path) {
try {
return p.toUri().toURL();
return path.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException("Could not get resource", e);
}
@ -67,11 +85,11 @@ public class WrapperClassLoader extends ClassLoader implements Closeable {
}
private @Nullable Path findSource(String path) {
for (Path source : sources) {
Path p = source.resolve(path);
if (Files.exists(p)) return p;
}
return null;
return findPaths(path).findFirst().orElse(null);
}
private Stream<Path> findPaths(String path) {
return sources.stream().map(s -> s.resolve(path)).filter(Files::exists);
}
@Override

View File

@ -18,11 +18,23 @@ public class WrapperStrap {
}
public static void bootstrap(Iterable<Path> jars, String mainClass, String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, URISyntaxException {
try (WrapperClassLoader loader = new WrapperClassLoader(jars)) {
try (WrapperClassLoader loader = new WrapperClassLoader(jars, SYSTEM_LOADER)) {
Thread.currentThread().setContextClassLoader(loader);
wrapperInit(loader);
loader.loadClass(mainClass)
.getDeclaredMethod("main", String[].class)
.invoke(null, new Object[]{args});
}
}
private static void wrapperInit(ClassLoader loader) {
try {
loader.loadClass("io.gitlab.jfronny.inceptum.common.Utils")
.getMethod("wrapperInit", ClassLoader.class)
.invoke(null, SYSTEM_LOADER);
} catch (Throwable e) {
System.out.println("Could not perform wrapper init, utils class probably moved");
e.printStackTrace();
}
}
}