-
Notifications
You must be signed in to change notification settings - Fork 458
/
LaunchCommand.java
116 lines (109 loc) · 3.7 KB
/
LaunchCommand.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package software.coley.recaf.launch;
import jakarta.annotation.Nullable;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import software.coley.recaf.Bootstrap;
import software.coley.recaf.RecafBuildConfig;
import software.coley.recaf.analytics.SystemInformation;
import software.coley.recaf.services.Service;
import software.coley.recaf.util.StringUtil;
import java.io.File;
import java.io.StringWriter;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
/**
* Launch arguments for Recaf.
*
* @author Matt Coley
* @see LaunchArguments Bean accesible form availble to CDI components.
*/
@Command(name = "recaf", mixinStandardHelpOptions = true, version = RecafBuildConfig.VERSION,
description = "Recaf: The modern Java reverse engineering tool.")
public class LaunchCommand implements Callable<Boolean> {
@Option(names = {"-i", "--input"}, description = "Input to load into a workspace on startup.")
private File input;
@Option(names = {"-s", "--script"}, description = "Script to run on startup.")
private File script;
@Option(names = {"-d", "--datadir"}, description = "Override the directory to store recaf info within.")
private File dataDir;
@Option(names = {"-h", "--headless"}, description = "Flag to skip over initializing the UI. Should be paired with -i or -s.")
private boolean headless;
@Option(names = {"-v", "--version"}, description = "Display the version information.")
private boolean version;
@Option(names = {"-l", "--listservices"}, description = "Display the version information.")
private boolean listServices;
@Option(names = {"-p", "--listprops"}, description = "Display system properties.")
private boolean dumpProperties;
@Override
public Boolean call() throws Exception {
boolean ret = false;
if (dataDir != null)
System.setProperty("RECAF_DIR", dataDir.getAbsolutePath());
if (version || listServices || dumpProperties)
System.out.println("======================= RECAF =======================");
if (version) {
System.out.printf("""
VERSION: %s
GIT-COMMIT: %s
GIT-TIME: %s
GIT-BRANCH: %s
=====================================================
""",
RecafBuildConfig.VERSION,
RecafBuildConfig.GIT_SHA,
RecafBuildConfig.GIT_DATE,
RecafBuildConfig.GIT_BRANCH
);
ret = true;
}
if (listServices) {
try {
BeanManager beanManager = Bootstrap.get().getContainer().getBeanManager();
List<Bean<?>> beans = beanManager.getBeans(Service.class).stream()
.sorted(Comparator.comparing(o -> o.getBeanClass().getName()))
.toList();
System.out.println("Services: " + beans.size());
for (Bean<?> bean : beans)
System.out.println(" - " + bean.getBeanClass().getName());
} catch (Throwable t) {
System.out.println("Error occurred iterating over services...");
System.out.println(StringUtil.traceToString(t));
}
System.out.println("=====================================================");
ret = true;
}
if (dumpProperties) {
StringWriter sw = new StringWriter();
SystemInformation.dump(sw);
System.out.println(sw);
System.out.println("=====================================================");
ret = true;
}
return ret;
}
/**
* @return Input to load into a workspace on startup.
*/
@Nullable
public File getInput() {
return input;
}
/**
* @return Script to run on startup.
*/
@Nullable
public File getScript() {
return script;
}
/**
* @return Flag to skip over initializing the UI.
*/
public boolean isHeadless() {
return headless;
}
}