Skip to content

Commit

Permalink
Startup args (#25)
Browse files Browse the repository at this point in the history
* Add support for startup args

* Add CLI args for mappings

Support:
- importing mappings
- hiding unmapped classes on side A
- not saving unmapped classes' matches

Also move ProjectConfig instantiation to a Builder

* Use better error message when plugin discovery fails

* Fix oversight with method args and vars

* Don't import side A mappings on side B

* Use better error message when plugin discovery fails

* Handle methods with inherited mapped names correctly

* Fix NPEs
  • Loading branch information
NebelNidas authored Mar 10, 2024
1 parent b8dc2d2 commit 9bc6538
Show file tree
Hide file tree
Showing 18 changed files with 599 additions and 186 deletions.
4 changes: 2 additions & 2 deletions src/main/java/matcher/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

public class Main {
public static void main(String[] args) {
Config.init();
PluginLoader.run();
Config.init(args);
PluginLoader.run(args);
Application.launch(Gui.class, args);
}
}
11 changes: 9 additions & 2 deletions src/main/java/matcher/Matcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,15 @@ public void initFromMatches(List<Path> inputDirs,
List<Path> classPathA = resolvePaths(inputDirs, cpFilesA);
List<Path> classPathB = resolvePaths(inputDirs, cpFilesB);

ProjectConfig config = new ProjectConfig(pathsA, pathsB, classPathA, classPathB, sharedClassPath, false,
nonObfuscatedClassPatternA, nonObfuscatedClassPatternB, nonObfuscatedMemberPatternA, nonObfuscatedMemberPatternB);
ProjectConfig config = new ProjectConfig.Builder(pathsA, pathsB)
.classPathA(new ArrayList<>(classPathA))
.classPathB(new ArrayList<>(classPathB))
.sharedClassPath(new ArrayList<>(sharedClassPath))
.nonObfuscatedClassPatternA(nonObfuscatedClassPatternA)
.nonObfuscatedClassPatternB(nonObfuscatedClassPatternB)
.nonObfuscatedMemberPatternA(nonObfuscatedMemberPatternA)
.nonObfuscatedMemberPatternB(nonObfuscatedMemberPatternB)
.build();
if (!config.isValid()) throw new IOException("invalid config");
Config.setProjectConfig(config);
Config.saveAsLast();
Expand Down
57 changes: 40 additions & 17 deletions src/main/java/matcher/PluginLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,57 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class PluginLoader {
public static void run() {
Path pluginFolder = Paths.get("plugins");
URL[] urls = new URL[0];

if (Files.isDirectory(pluginFolder)) {
try (Stream<Path> stream = Files.list(pluginFolder)) {
urls = stream
.filter(p -> p.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
.map(p -> {
try {
return p.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList()).toArray(urls);
public static void run(String[] args) {
List<Path> pluginPaths = new ArrayList<>();
pluginPaths.add(Paths.get("plugins"));

for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "--additional-plugins":
while (i+1 < args.length && !args[i+1].startsWith("--")) {
pluginPaths.add(Path.of(args[++i]));
}

break;
}
}

List<URL> urls = new ArrayList<>();

for (Path path : pluginPaths) {
try {
if (Files.isDirectory(path)) {
Stream<Path> stream = Files.list(path);
urls.addAll(stream
.filter(p -> p.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
.map(p -> {
try {
return p.toUri().toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
})
.collect(Collectors.toList()));
stream.close();
} else if (path.getFileName().toString().toLowerCase(Locale.ENGLISH).endsWith(".jar")) {
urls.add(path.toUri().toURL());
} else {
System.err.println("No plugin(s) found at " + path.toFile().getCanonicalPath());
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

URLClassLoader cl = new URLClassLoader(urls);
URLClassLoader cl = new URLClassLoader(urls.toArray(new URL[0]));

ServiceLoader<Plugin> pluginLoader = ServiceLoader.load(Plugin.class, cl);

Expand Down
25 changes: 20 additions & 5 deletions src/main/java/matcher/config/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
import java.util.prefs.Preferences;

public class Config {
public static void init() {
public static void init(String[] args) {
Preferences prefs = Preferences.userRoot(); // in ~/.java/.userPrefs

try {
if (prefs.nodeExists(userPrefFolder)) {
prefs = prefs.node(userPrefFolder);

if (prefs.nodeExists(lastProjectSetupKey)) setProjectConfig(new ProjectConfig(prefs.node(lastProjectSetupKey)));
if (prefs.nodeExists(lastProjectSetupKey)) setProjectConfig(new ProjectConfig.Builder(prefs.node(lastProjectSetupKey)).build());
setInputDirs(loadList(prefs, lastInputDirsKey, Config::deserializePath));
setVerifyInputFiles(prefs.getBoolean(lastVerifyInputFilesKey, true));
setUidConfig(new UidConfig(prefs));
Expand All @@ -26,6 +26,22 @@ public static void init() {
} catch (BackingStoreException e) {
// ignored
}

for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "--theme":
String themeId = args[++i];
Theme theme = Theme.getById(themeId);

if (theme == null) {
System.err.println("Startup arg '--theme' couldn't be applied, as there exists no theme with ID " + themeId + "!");
} else {
setTheme(theme);
}

break;
}
}
}

private Config() { }
Expand Down Expand Up @@ -78,11 +94,10 @@ public static boolean setUidConfig(UidConfig config) {
public static void setTheme(Theme value) {
if (value != null) {
theme = value;
saveTheme();
}
}

private static void saveTheme() {
public static void saveTheme() {
Preferences root = Preferences.userRoot().node(userPrefFolder);

try {
Expand Down Expand Up @@ -140,7 +155,7 @@ static Path deserializePath(String path) {
private static final String lastVerifyInputFilesKey = "last-verify-input-files";
private static final String themeKey = "theme";

private static ProjectConfig projectConfig = new ProjectConfig();
private static ProjectConfig projectConfig = ProjectConfig.EMPTY;
private static final List<Path> inputDirs = new ArrayList<>();
private static boolean verifyInputFiles = true;
private static UidConfig uidConfig = new UidConfig();
Expand Down
142 changes: 127 additions & 15 deletions src/main/java/matcher/config/ProjectConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,119 @@
import java.util.regex.PatternSyntaxException;

public class ProjectConfig {
public ProjectConfig() {
this(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), false, "", "", "", "");
}
public static class Builder {
public Builder(List<Path> pathsA, List<Path> pathsB) {
this.pathsA = pathsA;
this.pathsB = pathsB;
}

Builder(Preferences prefs) throws BackingStoreException {
pathsA = Config.loadList(prefs, pathsAKey, Config::deserializePath);
pathsB = Config.loadList(prefs, pathsBKey, Config::deserializePath);
classPathA = Config.loadList(prefs, classPathAKey, Config::deserializePath);
classPathB = Config.loadList(prefs, classPathBKey, Config::deserializePath);
sharedClassPath = Config.loadList(prefs, pathsSharedKey, Config::deserializePath);
inputsBeforeClassPath = prefs.getBoolean(inputsBeforeClassPathKey, false);

String storedMappingsPathA = prefs.get(mappingsPathAKey, null);
String storedMappingsPathB = prefs.get(mappingsPathBKey, null);
mappingsPathA = storedMappingsPathA == null ? null : Path.of(storedMappingsPathA);
mappingsPathB = storedMappingsPathB == null ? null : Path.of(storedMappingsPathB);
saveUnmappedMatches = prefs.getBoolean(inputsBeforeClassPathKey, false);

nonObfuscatedClassPatternA = prefs.get(nonObfuscatedClassPatternAKey, "");
nonObfuscatedClassPatternB = prefs.get(nonObfuscatedClassPatternBKey, "");
nonObfuscatedMemberPatternA = prefs.get(nonObfuscatedMemberPatternAKey, "");
nonObfuscatedMemberPatternB = prefs.get(nonObfuscatedMemberPatternBKey, "");
}

public Builder classPathA(List<Path> classPathA) {
this.classPathA = classPathA;
return this;
}

public Builder classPathB(List<Path> classPathB) {
this.classPathB = classPathB;
return this;
}

ProjectConfig(Preferences prefs) throws BackingStoreException {
this(Config.loadList(prefs, pathsAKey, Config::deserializePath),
Config.loadList(prefs, pathsBKey, Config::deserializePath),
Config.loadList(prefs, classPathAKey, Config::deserializePath),
Config.loadList(prefs, classPathBKey, Config::deserializePath),
Config.loadList(prefs, pathsSharedKey, Config::deserializePath),
prefs.getBoolean(inputsBeforeClassPathKey, false),
prefs.get(nonObfuscatedClassPatternAKey, ""),
prefs.get(nonObfuscatedClassPatternBKey, ""),
prefs.get(nonObfuscatedMemberPatternAKey, ""),
prefs.get(nonObfuscatedMemberPatternBKey, ""));
public Builder sharedClassPath(List<Path> sharedClassPath) {
this.sharedClassPath = sharedClassPath;
return this;
}

public Builder inputsBeforeClassPath(boolean inputsBeforeClassPath) {
this.inputsBeforeClassPath = inputsBeforeClassPath;
return this;
}

public Builder mappingsPathA(Path mappingsPathA) {
this.mappingsPathA = mappingsPathA;
return this;
}

public Builder mappingsPathB(Path mappingsPathB) {
this.mappingsPathB = mappingsPathB;
return this;
}

public Builder saveUnmappedMatches(boolean saveUnmappedMatches) {
this.saveUnmappedMatches = saveUnmappedMatches;
return this;
}

public Builder nonObfuscatedClassPatternA(String nonObfuscatedClassPatternA) {
this.nonObfuscatedClassPatternA = nonObfuscatedClassPatternA;
return this;
}

public Builder nonObfuscatedClassPatternB(String nonObfuscatedClassPatternB) {
this.nonObfuscatedClassPatternB = nonObfuscatedClassPatternB;
return this;
}

public Builder nonObfuscatedMemberPatternA(String nonObfuscatedMemberPatternA) {
this.nonObfuscatedMemberPatternA = nonObfuscatedMemberPatternA;
return this;
}

public Builder nonObfuscatedMemberPatternB(String nonObfuscatedMemberPatternB) {
this.nonObfuscatedMemberPatternB = nonObfuscatedMemberPatternB;
return this;
}

public ProjectConfig build() {
return new ProjectConfig(pathsA, pathsB, classPathA, classPathB, sharedClassPath, inputsBeforeClassPath, mappingsPathA, mappingsPathB, saveUnmappedMatches,
nonObfuscatedClassPatternA, nonObfuscatedClassPatternB, nonObfuscatedMemberPatternA, nonObfuscatedMemberPatternB);
}

protected final List<Path> pathsA;
protected final List<Path> pathsB;
protected List<Path> classPathA;
protected List<Path> classPathB;
protected List<Path> sharedClassPath;
protected boolean inputsBeforeClassPath;
protected Path mappingsPathA;
protected Path mappingsPathB;
protected boolean saveUnmappedMatches = true;
protected String nonObfuscatedClassPatternA;
protected String nonObfuscatedClassPatternB;
protected String nonObfuscatedMemberPatternA;
protected String nonObfuscatedMemberPatternB;
}

public ProjectConfig(List<Path> pathsA, List<Path> pathsB, List<Path> classPathA, List<Path> classPathB, List<Path> sharedClassPath, boolean inputsBeforeClassPath,
private ProjectConfig(List<Path> pathsA, List<Path> pathsB, List<Path> classPathA, List<Path> classPathB,
List<Path> sharedClassPath, boolean inputsBeforeClassPath, Path mappingsPathA, Path mappingsPathB, boolean saveUnmappedMatches,
String nonObfuscatedClassesPatternA, String nonObfuscatedClassesPatternB, String nonObfuscatedMemberPatternA, String nonObfuscatedMemberPatternB) {
this.pathsA = pathsA;
this.pathsB = pathsB;
this.classPathA = classPathA;
this.classPathB = classPathB;
this.sharedClassPath = sharedClassPath;
this.inputsBeforeClassPath = inputsBeforeClassPath;
this.mappingsPathA = mappingsPathA;
this.mappingsPathB = mappingsPathB;
this.saveUnmappedMatches = saveUnmappedMatches;
this.nonObfuscatedClassPatternA = nonObfuscatedClassesPatternA;
this.nonObfuscatedClassPatternB = nonObfuscatedClassesPatternB;
this.nonObfuscatedMemberPatternA = nonObfuscatedMemberPatternA;
Expand Down Expand Up @@ -64,6 +152,18 @@ public boolean hasInputsBeforeClassPath() {
return inputsBeforeClassPath;
}

public Path getMappingsPathA() {
return mappingsPathA;
}

public Path getMappingsPathB() {
return mappingsPathB;
}

public boolean isSaveUnmappedMatches() {
return saveUnmappedMatches;
}

public String getNonObfuscatedClassPatternA() {
return nonObfuscatedClassPatternA;
}
Expand Down Expand Up @@ -117,18 +217,27 @@ void save(Preferences prefs) throws BackingStoreException {
Config.saveList(prefs.node(classPathBKey), classPathB);
Config.saveList(prefs.node(pathsSharedKey), sharedClassPath);
prefs.putBoolean(inputsBeforeClassPathKey, inputsBeforeClassPath);
if (mappingsPathA != null) prefs.put(mappingsPathAKey, mappingsPathA.toString());
if (mappingsPathB != null) prefs.put(mappingsPathBKey, mappingsPathB.toString());
prefs.putBoolean(saveUnmappedMatchesKey, saveUnmappedMatches);
prefs.put(nonObfuscatedClassPatternAKey, nonObfuscatedClassPatternA);
prefs.put(nonObfuscatedClassPatternBKey, nonObfuscatedClassPatternB);
prefs.put(nonObfuscatedMemberPatternAKey, nonObfuscatedMemberPatternA);
prefs.put(nonObfuscatedMemberPatternBKey, nonObfuscatedMemberPatternB);
}

public static final ProjectConfig EMPTY = new ProjectConfig(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
false, null, null, true, "", "", "", "");

private static final String pathsAKey = "paths-a";
private static final String pathsBKey = "paths-b";
private static final String classPathAKey = "class-path-a";
private static final String classPathBKey = "class-path-b";
private static final String pathsSharedKey = "paths-shared";
private static final String inputsBeforeClassPathKey = "inputs-before-classpath";
private static final String mappingsPathAKey = "mappings-path-a";
private static final String mappingsPathBKey = "mappings-path-b";
private static final String saveUnmappedMatchesKey = "save-unmapped-matches";
private static final String nonObfuscatedClassPatternAKey = "non-obfuscated-class-pattern-a";
private static final String nonObfuscatedClassPatternBKey = "non-obfuscated-class-pattern-b";
private static final String nonObfuscatedMemberPatternAKey = "non-obfuscated-member-pattern-a";
Expand All @@ -139,6 +248,9 @@ void save(Preferences prefs) throws BackingStoreException {
private final List<Path> classPathA;
private final List<Path> classPathB;
private final List<Path> sharedClassPath;
private final Path mappingsPathA;
private final Path mappingsPathB;
private final boolean saveUnmappedMatches;
private final boolean inputsBeforeClassPath;
private final String nonObfuscatedClassPatternA;
private final String nonObfuscatedClassPatternB;
Expand Down
Loading

0 comments on commit 9bc6538

Please sign in to comment.