feat(cli): add option to disable plugins (#2277)
This commit is contained in:
@@ -264,6 +264,9 @@ public class JadxCLIArgs {
|
||||
@Parameter(names = { "-q", "--quiet" }, description = "turn off output (set --log-level to QUIET)")
|
||||
protected boolean quiet = false;
|
||||
|
||||
@Parameter(names = { "--disable-plugins" }, description = "comma separated list of plugin ids to disable")
|
||||
protected String disablePlugins = "";
|
||||
|
||||
@Parameter(names = { "--version" }, description = "print jadx version")
|
||||
protected boolean printVersion = false;
|
||||
|
||||
@@ -370,6 +373,7 @@ public class JadxCLIArgs {
|
||||
args.setIntegerFormat(integerFormat);
|
||||
args.setUseDxInput(useDx);
|
||||
args.setPluginOptions(pluginOptions);
|
||||
args.setDisabledPlugins(Arrays.stream(disablePlugins.split(",")).map(String::trim).collect(Collectors.toSet()));
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -580,6 +584,10 @@ public class JadxCLIArgs {
|
||||
return pluginOptions;
|
||||
}
|
||||
|
||||
public String getDisablePlugins() {
|
||||
return disablePlugins;
|
||||
}
|
||||
|
||||
static class RenameConverter implements IStringConverter<Set<RenameEnum>> {
|
||||
private final String paramName;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package jadx.cli;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
|
||||
@@ -10,7 +10,7 @@ import jadx.cli.commands.ICommand;
|
||||
import jadx.core.utils.exceptions.JadxArgsValidateException;
|
||||
|
||||
public class JadxCLICommands {
|
||||
private static final Map<String, ICommand> COMMANDS_MAP = new TreeMap<>();
|
||||
private static final Map<String, ICommand> COMMANDS_MAP = new LinkedHashMap<>();
|
||||
|
||||
static {
|
||||
JadxCLICommands.register(new CommandPlugins());
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package jadx.cli.commands;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
|
||||
import jadx.api.plugins.JadxPluginInfo;
|
||||
import jadx.cli.JCommanderWrapper;
|
||||
import jadx.cli.LogHelper;
|
||||
import jadx.plugins.tools.JadxPluginsList;
|
||||
import jadx.plugins.tools.JadxPluginsTools;
|
||||
import jadx.plugins.tools.data.JadxPluginMetadata;
|
||||
@@ -24,6 +29,9 @@ public class CommandPlugins implements ICommand {
|
||||
@Parameter(names = { "-l", "--list" }, description = "list installed plugins")
|
||||
protected boolean list;
|
||||
|
||||
@Parameter(names = { "--list-all" }, description = "list all plugins including bundled and dropins")
|
||||
protected boolean listAll;
|
||||
|
||||
@Parameter(names = { "-a", "--available" }, description = "list available plugins")
|
||||
protected boolean available;
|
||||
|
||||
@@ -53,8 +61,12 @@ public class CommandPlugins implements ICommand {
|
||||
jcw.printUsage(subCommander);
|
||||
return;
|
||||
}
|
||||
if (!subCommander.getUnknownOptions().isEmpty()) {
|
||||
System.out.println("Error: found unknown options: " + subCommander.getUnknownOptions());
|
||||
Set<String> unknownOptions = new HashSet<>(subCommander.getUnknownOptions());
|
||||
boolean verbose = unknownOptions.remove("-v") || unknownOptions.remove("--verbose");
|
||||
LogHelper.setLogLevel(verbose ? LogHelper.LogLevelEnum.DEBUG : LogHelper.LogLevelEnum.INFO);
|
||||
|
||||
if (!unknownOptions.isEmpty()) {
|
||||
System.out.println("Error: found unknown options: " + unknownOptions);
|
||||
}
|
||||
|
||||
if (install != null) {
|
||||
@@ -79,7 +91,10 @@ public class CommandPlugins implements ICommand {
|
||||
}
|
||||
}
|
||||
if (list) {
|
||||
printInstalledPlugins();
|
||||
printPlugins(JadxPluginsTools.getInstance().getInstalled());
|
||||
}
|
||||
if (listAll) {
|
||||
printAllPlugins();
|
||||
}
|
||||
|
||||
if (available) {
|
||||
@@ -107,13 +122,11 @@ public class CommandPlugins implements ICommand {
|
||||
}
|
||||
}
|
||||
|
||||
private static void printInstalledPlugins() {
|
||||
List<JadxPluginMetadata> installed = JadxPluginsTools.getInstance().getInstalled();
|
||||
private static void printPlugins(List<JadxPluginMetadata> installed) {
|
||||
System.out.println("Installed plugins: " + installed.size());
|
||||
for (JadxPluginMetadata plugin : installed) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" - ");
|
||||
sb.append(plugin.getPluginId());
|
||||
sb.append(" - ").append(plugin.getPluginId());
|
||||
String version = plugin.getVersion();
|
||||
if (version != null) {
|
||||
sb.append(" (").append(version).append(')');
|
||||
@@ -121,14 +134,28 @@ public class CommandPlugins implements ICommand {
|
||||
if (plugin.isDisabled()) {
|
||||
sb.append(" (disabled)");
|
||||
}
|
||||
sb.append(" - ");
|
||||
sb.append(plugin.getName());
|
||||
sb.append(": ");
|
||||
sb.append(plugin.getDescription());
|
||||
sb.append(" - ").append(plugin.getName());
|
||||
sb.append(": ").append(plugin.getDescription());
|
||||
System.out.println(sb);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printAllPlugins() {
|
||||
List<JadxPluginMetadata> installed = JadxPluginsTools.getInstance().getInstalled();
|
||||
printPlugins(installed);
|
||||
Set<String> installedSet = installed.stream().map(JadxPluginMetadata::getPluginId).collect(Collectors.toSet());
|
||||
|
||||
List<JadxPluginInfo> plugins = JadxPluginsTools.getInstance().getAllPluginsInfo();
|
||||
System.out.println("Other plugins: " + plugins.size());
|
||||
for (JadxPluginInfo plugin : plugins) {
|
||||
if (!installedSet.contains(plugin.getPluginId())) {
|
||||
System.out.println(" - " + plugin.getPluginId()
|
||||
+ " - " + plugin.getName()
|
||||
+ ": " + plugin.getDescription());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void installPlugin(String locationId) {
|
||||
JadxPluginMetadata plugin = JadxPluginsTools.getInstance().install(locationId);
|
||||
System.out.println("Plugin installed: " + plugin.getPluginId() + ":" + plugin.getVersion());
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -194,6 +195,8 @@ public class JadxArgs implements Closeable {
|
||||
|
||||
private Map<String, String> pluginOptions = new HashMap<>();
|
||||
|
||||
private Set<String> disabledPlugins = new HashSet<>();
|
||||
|
||||
private JadxPluginLoader pluginLoader = new JadxBasePluginLoader();
|
||||
|
||||
private boolean loadJadxClsSetFile = true;
|
||||
@@ -766,6 +769,14 @@ public class JadxArgs implements Closeable {
|
||||
this.pluginOptions = pluginOptions;
|
||||
}
|
||||
|
||||
public Set<String> getDisabledPlugins() {
|
||||
return disabledPlugins;
|
||||
}
|
||||
|
||||
public void setDisabledPlugins(Set<String> disabledPlugins) {
|
||||
this.disabledPlugins = disabledPlugins;
|
||||
}
|
||||
|
||||
public JadxPluginLoader getPluginLoader() {
|
||||
return pluginLoader;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ public final class JadxDecompiler implements Closeable {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JadxDecompiler.class);
|
||||
|
||||
private final JadxArgs args;
|
||||
private final JadxPluginManager pluginManager = new JadxPluginManager(this);
|
||||
private final JadxPluginManager pluginManager;
|
||||
private final List<ICodeLoader> loadedInputs = new ArrayList<>();
|
||||
|
||||
private RootNode root;
|
||||
@@ -93,7 +93,7 @@ public final class JadxDecompiler implements Closeable {
|
||||
private List<ResourceFile> resources;
|
||||
|
||||
private final IDecompileScheduler decompileScheduler = new DecompilerScheduler();
|
||||
private final ResourcesLoader resourcesLoader = new ResourcesLoader(this);
|
||||
private final ResourcesLoader resourcesLoader;
|
||||
|
||||
private final List<ICodeLoader> customCodeLoaders = new ArrayList<>();
|
||||
private final List<CustomResourcesLoader> customResourcesLoaders = new ArrayList<>();
|
||||
@@ -106,7 +106,9 @@ public final class JadxDecompiler implements Closeable {
|
||||
}
|
||||
|
||||
public JadxDecompiler(JadxArgs args) {
|
||||
this.args = args;
|
||||
this.args = Objects.requireNonNull(args);
|
||||
this.pluginManager = new JadxPluginManager(this);
|
||||
this.resourcesLoader = new ResourcesLoader(this);
|
||||
}
|
||||
|
||||
public void load() {
|
||||
|
||||
@@ -4,12 +4,14 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -26,6 +28,7 @@ public class JadxPluginManager {
|
||||
|
||||
private final JadxDecompiler decompiler;
|
||||
private final JadxPluginsData pluginsData;
|
||||
private final Set<String> disabledPlugins;
|
||||
private final SortedSet<PluginContext> allPlugins = new TreeSet<>();
|
||||
private final SortedSet<PluginContext> resolvedPlugins = new TreeSet<>();
|
||||
private final Map<String, String> provideSuggestions = new TreeMap<>();
|
||||
@@ -35,6 +38,7 @@ public class JadxPluginManager {
|
||||
public JadxPluginManager(JadxDecompiler decompiler) {
|
||||
this.decompiler = decompiler;
|
||||
this.pluginsData = new JadxPluginsData(decompiler, this);
|
||||
this.disabledPlugins = decompiler.getArgs().getDisabledPlugins();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,12 +59,19 @@ public class JadxPluginManager {
|
||||
public void register(JadxPlugin plugin) {
|
||||
Objects.requireNonNull(plugin);
|
||||
PluginContext addedPlugin = addPlugin(plugin);
|
||||
if (addedPlugin == null) {
|
||||
LOG.debug("Can't register plugin, it was disabled: {}", plugin.getPluginInfo().getPluginId());
|
||||
return;
|
||||
}
|
||||
LOG.debug("Register plugin: {}", addedPlugin.getPluginId());
|
||||
resolve();
|
||||
}
|
||||
|
||||
private PluginContext addPlugin(JadxPlugin plugin) {
|
||||
private @Nullable PluginContext addPlugin(JadxPlugin plugin) {
|
||||
PluginContext pluginContext = new PluginContext(decompiler, pluginsData, plugin);
|
||||
if (disabledPlugins.contains(pluginContext.getPluginId())) {
|
||||
return null;
|
||||
}
|
||||
LOG.debug("Loading plugin: {}", pluginContext);
|
||||
if (!allPlugins.add(pluginContext)) {
|
||||
throw new IllegalArgumentException("Duplicate plugin id: " + pluginContext + ", class " + plugin.getClass());
|
||||
|
||||
@@ -61,6 +61,7 @@ public class JadxSettings extends JadxCLIArgs {
|
||||
static final Set<String> SKIP_FIELDS = new HashSet<>(Arrays.asList(
|
||||
"files", "input", "outDir", "outDirSrc", "outDirRes", "outputFormat",
|
||||
"deobfuscationMapFile",
|
||||
"disablePlugins",
|
||||
"verbose", "quiet", "logLevel",
|
||||
"printVersion", "printHelp"));
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ public class CollectPlugins {
|
||||
.ifPresent(decompiler -> allPlugins.addAll(decompiler.getPluginManager().getResolvedPluginContexts()));
|
||||
|
||||
// collect and init not loaded plugins in new temp context
|
||||
try (JadxDecompiler decompiler = new JadxDecompiler(new JadxArgs())) {
|
||||
JadxArgs jadxArgs = mainWindow.getSettings().toJadxArgs();
|
||||
try (JadxDecompiler decompiler = new JadxDecompiler(jadxArgs)) {
|
||||
JadxPluginManager pluginManager = decompiler.getPluginManager();
|
||||
pluginManager.registerAddPluginListener(pluginContext -> {
|
||||
AppContext appContext = new AppContext();
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -115,6 +116,20 @@ public class JadxPluginsTools {
|
||||
return loadPluginsJson().getInstalled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all loadable plugins info (including installed, bundled and dropins).
|
||||
* <br>
|
||||
* For only installed plugins prefer {@link jadx.plugins.tools.JadxPluginsTools#getInstalled}
|
||||
* method.
|
||||
*/
|
||||
public List<JadxPluginInfo> getAllPluginsInfo() {
|
||||
try (JadxExternalPluginsLoader pluginsLoader = new JadxExternalPluginsLoader()) {
|
||||
return pluginsLoader.load().stream()
|
||||
.map(JadxPlugin::getPluginInfo)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
public List<Path> getAllPluginJars() {
|
||||
List<Path> list = new ArrayList<>();
|
||||
for (JadxPluginMetadata pluginMetadata : loadPluginsJson().getInstalled()) {
|
||||
|
||||
Reference in New Issue
Block a user