feat: allow to disable installed plugins (#2277)
This commit is contained in:
@@ -33,6 +33,12 @@ public class CommandPlugins implements ICommand {
|
||||
@Parameter(names = { "--uninstall" }, description = "uninstall plugin with pluginId")
|
||||
protected String uninstall;
|
||||
|
||||
@Parameter(names = { "--disable" }, description = "disable plugin with pluginId")
|
||||
protected String disable;
|
||||
|
||||
@Parameter(names = { "--enable" }, description = "enable plugin with pluginId")
|
||||
protected String enable;
|
||||
|
||||
@Parameter(names = { "-h", "--help" }, description = "print this help", help = true)
|
||||
protected boolean printHelp = false;
|
||||
|
||||
@@ -47,6 +53,10 @@ public class CommandPlugins implements ICommand {
|
||||
jcw.printUsage(subCommander);
|
||||
return;
|
||||
}
|
||||
if (!subCommander.getUnknownOptions().isEmpty()) {
|
||||
System.out.println("Error: found unknown options: " + subCommander.getUnknownOptions());
|
||||
}
|
||||
|
||||
if (install != null) {
|
||||
installPlugin(install);
|
||||
}
|
||||
@@ -69,26 +79,54 @@ public class CommandPlugins implements ICommand {
|
||||
}
|
||||
}
|
||||
if (list) {
|
||||
List<JadxPluginMetadata> installed = JadxPluginsTools.getInstance().getInstalled();
|
||||
System.out.println("Installed plugins: " + installed.size());
|
||||
int i = 1;
|
||||
for (JadxPluginMetadata plugin : installed) {
|
||||
System.out.println(" " + (i++) + ") "
|
||||
+ plugin.getPluginId() + " (" + plugin.getVersion() + ") - "
|
||||
+ plugin.getName() + ": " + plugin.getDescription());
|
||||
}
|
||||
printInstalledPlugins();
|
||||
}
|
||||
|
||||
if (available) {
|
||||
List<JadxPluginMetadata> availableList = JadxPluginsList.getInstance().get();
|
||||
System.out.println("Available plugins: " + availableList.size());
|
||||
int i = 1;
|
||||
for (JadxPluginMetadata plugin : availableList) {
|
||||
System.out.println(" " + (i++) + ") "
|
||||
+ plugin.getName() + ": " + plugin.getDescription()
|
||||
System.out.println(" - " + plugin.getName() + ": " + plugin.getDescription()
|
||||
+ " (" + plugin.getLocationId() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (disable != null) {
|
||||
if (JadxPluginsTools.getInstance().changeDisabledStatus(disable, true)) {
|
||||
System.out.println("Plugin '" + disable + "' disabled.");
|
||||
} else {
|
||||
System.out.println("Plugin '" + disable + "' already disabled.");
|
||||
}
|
||||
}
|
||||
if (enable != null) {
|
||||
if (JadxPluginsTools.getInstance().changeDisabledStatus(enable, false)) {
|
||||
System.out.println("Plugin '" + enable + "' enabled.");
|
||||
} else {
|
||||
System.out.println("Plugin '" + enable + "' already enabled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void printInstalledPlugins() {
|
||||
List<JadxPluginMetadata> installed = JadxPluginsTools.getInstance().getInstalled();
|
||||
System.out.println("Installed plugins: " + installed.size());
|
||||
for (JadxPluginMetadata plugin : installed) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" - ");
|
||||
sb.append(plugin.getPluginId());
|
||||
String version = plugin.getVersion();
|
||||
if (version != null) {
|
||||
sb.append(" (").append(version).append(')');
|
||||
}
|
||||
if (plugin.isDisabled()) {
|
||||
sb.append(" (disabled)");
|
||||
}
|
||||
sb.append(" - ");
|
||||
sb.append(plugin.getName());
|
||||
sb.append(": ");
|
||||
sb.append(plugin.getDescription());
|
||||
System.out.println(sb);
|
||||
}
|
||||
}
|
||||
|
||||
private void installPlugin(String locationId) {
|
||||
|
||||
@@ -93,13 +93,14 @@ public final class JadxDecompiler implements Closeable {
|
||||
private List<ResourceFile> resources;
|
||||
|
||||
private final IDecompileScheduler decompileScheduler = new DecompilerScheduler();
|
||||
private final JadxEventsImpl events = new JadxEventsImpl();
|
||||
private final ResourcesLoader resourcesLoader = new ResourcesLoader(this);
|
||||
|
||||
private final List<ICodeLoader> customCodeLoaders = new ArrayList<>();
|
||||
private final List<CustomResourcesLoader> customResourcesLoaders = new ArrayList<>();
|
||||
private final Map<JadxPassType, List<JadxPass>> customPasses = new HashMap<>();
|
||||
|
||||
private IJadxEvents events = new JadxEventsImpl();
|
||||
|
||||
public JadxDecompiler() {
|
||||
this(new JadxArgs());
|
||||
}
|
||||
@@ -666,6 +667,10 @@ public final class JadxDecompiler implements Closeable {
|
||||
return events;
|
||||
}
|
||||
|
||||
public void setEventsImpl(IJadxEvents eventsImpl) {
|
||||
this.events = eventsImpl;
|
||||
}
|
||||
|
||||
public void addCustomCodeLoader(ICodeLoader customCodeLoader) {
|
||||
customCodeLoaders.add(customCodeLoader);
|
||||
}
|
||||
|
||||
@@ -15,4 +15,15 @@ public interface IJadxEvents {
|
||||
* For public event types check {@link JadxEvents} class.
|
||||
*/
|
||||
<E extends IJadxEvent> void addListener(JadxEventType<E> eventType, Consumer<E> listener);
|
||||
|
||||
/**
|
||||
* Remove listener for specific event.
|
||||
* Listener should be same or equal object.
|
||||
*/
|
||||
<E extends IJadxEvent> void removeListener(JadxEventType<E> eventType, Consumer<E> listener);
|
||||
|
||||
/**
|
||||
* Clear all listeners.
|
||||
*/
|
||||
void reset();
|
||||
}
|
||||
|
||||
@@ -6,4 +6,13 @@ public abstract class JadxEventType<T extends IJadxEvent> {
|
||||
return new JadxEventType<>() {
|
||||
};
|
||||
}
|
||||
|
||||
public static <E extends IJadxEvent> JadxEventType<E> create(String name) {
|
||||
return new JadxEventType<>() {
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,17 +16,17 @@ public class JadxEvents {
|
||||
/**
|
||||
* Notify about renaming done by user (GUI only).
|
||||
*/
|
||||
public static final JadxEventType<NodeRenamedByUser> NODE_RENAMED_BY_USER = create();
|
||||
public static final JadxEventType<NodeRenamedByUser> NODE_RENAMED_BY_USER = create("NODE_RENAMED_BY_USER");
|
||||
|
||||
/**
|
||||
* Request reload of a current project (GUI only).
|
||||
*/
|
||||
public static final JadxEventType<ReloadProject> RELOAD_PROJECT = create();
|
||||
public static final JadxEventType<ReloadProject> RELOAD_PROJECT = create("RELOAD_PROJECT");
|
||||
|
||||
/**
|
||||
* Request reload of a settings window (GUI only).
|
||||
* Useful for a reload custom settings group which was set with
|
||||
* {@link JadxGuiSettings#setCustomSettingsGroup(ISettingsGroup)}.
|
||||
*/
|
||||
public static final JadxEventType<ReloadSettingsWindow> RELOAD_SETTINGS_WINDOW = create();
|
||||
public static final JadxEventType<ReloadSettingsWindow> RELOAD_SETTINGS_WINDOW = create("RELOAD_SETTINGS_WINDOW");
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public class Consts {
|
||||
public static final boolean DEBUG_FINALLY = false;
|
||||
public static final boolean DEBUG_ATTRIBUTES = false;
|
||||
public static final boolean DEBUG_RESTRUCTURE = false;
|
||||
public static final boolean DEBUG_EVENTS = true;
|
||||
public static final boolean DEBUG_EVENTS = Jadx.isDevVersion();
|
||||
|
||||
public static final String CLASS_OBJECT = "java.lang.Object";
|
||||
public static final String CLASS_STRING = "java.lang.String";
|
||||
|
||||
@@ -26,8 +26,20 @@ public class JadxEventsImpl implements IJadxEvents {
|
||||
@Override
|
||||
public <E extends IJadxEvent> void addListener(JadxEventType<E> eventType, Consumer<E> listener) {
|
||||
manager.addListener(eventType, listener);
|
||||
if (Consts.DEBUG_EVENTS) {
|
||||
LOG.debug("add listener for: {}, stats: {}", eventType, manager.listenersDebugStats());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends IJadxEvent> void removeListener(JadxEventType<E> eventType, Consumer<E> listener) {
|
||||
manager.removeListener(eventType, listener);
|
||||
if (Consts.DEBUG_EVENTS) {
|
||||
LOG.debug("remove listener for: {}, stats: {}", eventType, manager.listenersDebugStats());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
manager.reset();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -35,6 +36,14 @@ public class JadxEventsManager {
|
||||
.add((Consumer<IJadxEvent>) listener);
|
||||
}
|
||||
|
||||
public synchronized <E extends IJadxEvent> boolean removeListener(JadxEventType<E> eventType, Consumer<E> listener) {
|
||||
List<Consumer<IJadxEvent>> eventListeners = listeners.get(eventType);
|
||||
if (eventListeners != null) {
|
||||
return eventListeners.remove(listener);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void send(IJadxEvent event) {
|
||||
List<Consumer<IJadxEvent>> consumers = listeners.get(event.getType());
|
||||
if (consumers != null) {
|
||||
@@ -58,4 +67,12 @@ public class JadxEventsManager {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String listenersDebugStats() {
|
||||
return listeners.entrySet()
|
||||
.stream()
|
||||
.filter(p -> !p.getValue().isEmpty())
|
||||
.map(p -> p.getKey() + ":" + p.getValue().size())
|
||||
.collect(Collectors.joining(", ", "[", "]"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,8 @@ public class JadxWrapper {
|
||||
decompiler = new JadxDecompiler(jadxArgs);
|
||||
guiPluginsContext = initGuiPluginsContext(decompiler, mainWindow);
|
||||
initUsageCache(jadxArgs);
|
||||
decompiler.setEventsImpl(mainWindow.events());
|
||||
|
||||
decompiler.load();
|
||||
initCodeCache();
|
||||
}
|
||||
@@ -159,6 +161,11 @@ public class JadxWrapper {
|
||||
guiPluginsContext.reset();
|
||||
}
|
||||
|
||||
public void reloadPasses() {
|
||||
resetGuiPluginsContext();
|
||||
decompiler.reloadPasses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the complete list of classes
|
||||
*/
|
||||
|
||||
@@ -7,5 +7,5 @@ import static jadx.api.plugins.events.JadxEventType.create;
|
||||
|
||||
public class JadxGuiEvents {
|
||||
|
||||
public static final JadxEventType<TreeUpdate> TREE_UPDATE = create();
|
||||
public static final JadxEventType<TreeUpdate> TREE_UPDATE = create("TREE_UPDATE");
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class RenameService {
|
||||
|
||||
public static void init(MainWindow mainWindow) {
|
||||
RenameService renameService = new RenameService(mainWindow);
|
||||
mainWindow.events().addListener(JadxEvents.NODE_RENAMED_BY_USER, renameService::process);
|
||||
mainWindow.events().global().addListener(JadxEvents.NODE_RENAMED_BY_USER, renameService::process);
|
||||
}
|
||||
|
||||
private final MainWindow mainWindow;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package jadx.gui.events.types;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jadx.api.plugins.events.IJadxEvent;
|
||||
import jadx.api.plugins.events.IJadxEvents;
|
||||
import jadx.api.plugins.events.JadxEventType;
|
||||
import jadx.core.plugins.events.JadxEventsImpl;
|
||||
|
||||
/**
|
||||
* Special events implementation to operate on both: global UI and project events.
|
||||
* Project events hold listeners only while a project opened and reset them on close.
|
||||
*/
|
||||
public class JadxGuiEventsImpl implements IJadxEvents {
|
||||
|
||||
private final IJadxEvents global = new JadxEventsImpl();
|
||||
private final IJadxEvents project = new JadxEventsImpl();
|
||||
|
||||
public IJadxEvents global() {
|
||||
return global;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(IJadxEvent event) {
|
||||
global.send(event);
|
||||
project.send(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends IJadxEvent> void addListener(JadxEventType<E> eventType, Consumer<E> listener) {
|
||||
project.addListener(eventType, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E extends IJadxEvent> void removeListener(JadxEventType<E> eventType, Consumer<E> listener) {
|
||||
project.removeListener(eventType, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
project.reset();
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import org.slf4j.LoggerFactory;
|
||||
import kotlin.script.experimental.api.ScriptDiagnostic;
|
||||
import kotlin.script.experimental.api.ScriptDiagnostic.Severity;
|
||||
|
||||
import jadx.gui.JadxWrapper;
|
||||
import jadx.gui.logs.LogOptions;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.LineNumbersMode;
|
||||
@@ -137,9 +136,7 @@ public class ScriptContentPanel extends AbstractCodeContentPanel {
|
||||
MainWindow mainWindow = tabbedPane.getMainWindow();
|
||||
mainWindow.getBackgroundExecutor().execute(NLS.str("script.run"), () -> {
|
||||
try {
|
||||
JadxWrapper wrapper = mainWindow.getWrapper();
|
||||
wrapper.resetGuiPluginsContext();
|
||||
wrapper.getDecompiler().reloadPasses();
|
||||
mainWindow.getWrapper().reloadPasses();
|
||||
} catch (Exception e) {
|
||||
scriptLog.error("Passes reload failed", e);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
@@ -54,6 +55,7 @@ import jadx.api.args.IntegerFormat;
|
||||
import jadx.api.args.ResourceNameSource;
|
||||
import jadx.api.args.UseSourceNameAsClassNameAlias;
|
||||
import jadx.api.plugins.events.JadxEvents;
|
||||
import jadx.api.plugins.events.types.ReloadSettingsWindow;
|
||||
import jadx.api.plugins.gui.ISettingsGroup;
|
||||
import jadx.gui.settings.JadxSettings;
|
||||
import jadx.gui.settings.JadxSettingsAdapter;
|
||||
@@ -85,6 +87,7 @@ public class JadxSettingsWindow extends JDialog {
|
||||
private final transient String startSettings;
|
||||
private final transient String startSettingsHash;
|
||||
private final transient LangLocale prevLang;
|
||||
private final transient Consumer<ReloadSettingsWindow> reloadListener;
|
||||
|
||||
private transient boolean needReload = false;
|
||||
private transient SettingsTree tree;
|
||||
@@ -107,8 +110,8 @@ public class JadxSettingsWindow extends JDialog {
|
||||
if (!mainWindow.getSettings().loadWindowPos(this)) {
|
||||
setSize(700, 800);
|
||||
}
|
||||
mainWindow.events().addListener(JadxEvents.RELOAD_SETTINGS_WINDOW, r -> UiUtils.uiRun(this::reloadUI));
|
||||
mainWindow.events().addListener(JadxEvents.RELOAD_PROJECT, r -> UiUtils.uiRun(this::reloadUI));
|
||||
reloadListener = ev -> UiUtils.uiRun(this::reloadUI);
|
||||
mainWindow.events().global().addListener(JadxEvents.RELOAD_SETTINGS_WINDOW, reloadListener);
|
||||
}
|
||||
|
||||
private void reloadUI() {
|
||||
@@ -773,6 +776,7 @@ public class JadxSettingsWindow extends JDialog {
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
mainWindow.events().global().removeListener(JadxEvents.RELOAD_SETTINGS_WINDOW, reloadListener);
|
||||
settings.saveWindowPos(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ abstract class BasePluginListNode {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isDisabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public PluginAction getAction() {
|
||||
return PluginAction.NONE;
|
||||
}
|
||||
|
||||
@@ -2,21 +2,18 @@ package jadx.gui.settings.ui.plugins;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.plugins.PluginContext;
|
||||
import jadx.plugins.tools.data.JadxPluginMetadata;
|
||||
|
||||
public class InstalledPluginNode extends BasePluginListNode {
|
||||
private final PluginContext plugin;
|
||||
private final JadxPluginMetadata metadata;
|
||||
|
||||
public InstalledPluginNode(PluginContext plugin, @Nullable JadxPluginMetadata metadata) {
|
||||
this.plugin = plugin;
|
||||
public InstalledPluginNode(JadxPluginMetadata metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getTitle() {
|
||||
return plugin.getPluginInfo().getName();
|
||||
return metadata.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,37 +23,36 @@ public class InstalledPluginNode extends BasePluginListNode {
|
||||
|
||||
@Override
|
||||
public String getPluginId() {
|
||||
return plugin.getPluginId();
|
||||
return metadata.getPluginId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return plugin.getPluginInfo().getDescription();
|
||||
return metadata.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHomepage() {
|
||||
return plugin.getPluginInfo().getHomepage();
|
||||
return metadata.getHomepage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PluginAction getAction() {
|
||||
if (metadata != null) {
|
||||
return PluginAction.UNINSTALL;
|
||||
}
|
||||
return PluginAction.NONE;
|
||||
return PluginAction.UNINSTALL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getVersion() {
|
||||
if (metadata != null) {
|
||||
return metadata.getVersion();
|
||||
}
|
||||
return null;
|
||||
return metadata.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisabled() {
|
||||
return metadata.isDisabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return plugin.getPluginInfo().getName();
|
||||
return metadata.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package jadx.gui.settings.ui.plugins;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.plugins.PluginContext;
|
||||
|
||||
public class LoadedPluginNode extends BasePluginListNode {
|
||||
private final PluginContext plugin;
|
||||
|
||||
public LoadedPluginNode(PluginContext plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getTitle() {
|
||||
return plugin.getPluginInfo().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDetails() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPluginId() {
|
||||
return plugin.getPluginId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return plugin.getPluginInfo().getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHomepage() {
|
||||
return plugin.getPluginInfo().getHomepage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return plugin.getPluginInfo().getName();
|
||||
}
|
||||
}
|
||||
@@ -53,9 +53,9 @@ public class PluginSettings {
|
||||
}
|
||||
|
||||
public ISettingsGroup build() {
|
||||
List<PluginContext> installedPlugins = new CollectPlugins(mainWindow).build();
|
||||
ISettingsGroup pluginsGroup = new PluginSettingsGroup(this, mainWindow, installedPlugins);
|
||||
for (PluginContext context : installedPlugins) {
|
||||
List<PluginContext> collectedPlugins = new CollectPlugins(mainWindow).build();
|
||||
ISettingsGroup pluginsGroup = new PluginSettingsGroup(this, mainWindow, collectedPlugins);
|
||||
for (PluginContext context : collectedPlugins) {
|
||||
ISettingsGroup pluginGroup = addPluginGroup(context);
|
||||
if (pluginGroup != null) {
|
||||
pluginsGroup.getSubGroups().add(pluginGroup);
|
||||
@@ -98,6 +98,13 @@ public class PluginSettings {
|
||||
});
|
||||
}
|
||||
|
||||
public void changeDisableStatus(String pluginId, boolean disabled) {
|
||||
mainWindow.getBackgroundExecutor().execute(
|
||||
NLS.str("preferences.plugins.task.status"),
|
||||
() -> JadxPluginsTools.getInstance().changeDisabledStatus(pluginId, disabled),
|
||||
s -> requestReload());
|
||||
}
|
||||
|
||||
void updateAll() {
|
||||
mainWindow.getBackgroundExecutor().execute(NLS.str("preferences.plugins.task.updating"), () -> {
|
||||
List<JadxPluginUpdate> updates = JadxPluginsTools.getInstance().updateAll();
|
||||
@@ -113,7 +120,7 @@ public class PluginSettings {
|
||||
private ISettingsGroup addPluginGroup(PluginContext context) {
|
||||
JadxGuiContext guiContext = context.getGuiContext();
|
||||
if (guiContext instanceof GuiPluginContext) {
|
||||
GuiPluginContext pluginGuiContext = ((GuiPluginContext) guiContext);
|
||||
GuiPluginContext pluginGuiContext = (GuiPluginContext) guiContext;
|
||||
ISettingsGroup customSettingsGroup = pluginGuiContext.getCustomSettingsGroup();
|
||||
if (customSettingsGroup != null) {
|
||||
return customSettingsGroup;
|
||||
|
||||
@@ -7,9 +7,8 @@ import java.awt.Font;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -52,15 +51,15 @@ class PluginSettingsGroup implements ISettingsGroup {
|
||||
private final MainWindow mainWindow;
|
||||
private final String title;
|
||||
private final List<ISettingsGroup> subGroups = new ArrayList<>();
|
||||
private final List<PluginContext> installedPlugins;
|
||||
private final List<PluginContext> collectedPlugins;
|
||||
|
||||
private JPanel detailsPanel;
|
||||
|
||||
public PluginSettingsGroup(PluginSettings pluginSettings, MainWindow mainWindow, List<PluginContext> installedPlugins) {
|
||||
public PluginSettingsGroup(PluginSettings pluginSettings, MainWindow mainWindow, List<PluginContext> collectedPlugins) {
|
||||
this.pluginsSettings = pluginSettings;
|
||||
this.mainWindow = mainWindow;
|
||||
this.title = NLS.str("preferences.plugins");
|
||||
this.installedPlugins = installedPlugins;
|
||||
this.collectedPlugins = collectedPlugins;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,17 +123,21 @@ class PluginSettingsGroup implements ISettingsGroup {
|
||||
|
||||
private void applyData(DefaultListModel<BasePluginListNode> listModel) {
|
||||
List<JadxPluginMetadata> installed = JadxPluginsTools.getInstance().getInstalled();
|
||||
Map<String, JadxPluginMetadata> installedMap = new HashMap<>(installed.size());
|
||||
installed.forEach(p -> installedMap.put(p.getPluginId(), p));
|
||||
|
||||
List<BasePluginListNode> nodes = new ArrayList<>(installed.size() + 3);
|
||||
for (PluginContext plugin : installedPlugins) {
|
||||
nodes.add(new InstalledPluginNode(plugin, installedMap.get(plugin.getPluginId())));
|
||||
List<BasePluginListNode> nodes = new ArrayList<>(installed.size() + collectedPlugins.size());
|
||||
Set<String> installedSet = new HashSet<>(installed.size());
|
||||
for (JadxPluginMetadata pluginMetadata : installed) {
|
||||
installedSet.add(pluginMetadata.getPluginId());
|
||||
nodes.add(new InstalledPluginNode(pluginMetadata));
|
||||
}
|
||||
for (PluginContext plugin : collectedPlugins) {
|
||||
if (!installedSet.contains(plugin.getPluginId())) {
|
||||
nodes.add(new LoadedPluginNode(plugin));
|
||||
}
|
||||
}
|
||||
nodes.sort(Comparator.comparing(BasePluginListNode::getTitle));
|
||||
|
||||
fillListModel(listModel, nodes, Collections.emptyList());
|
||||
loadAvailablePlugins(listModel, nodes, installedPlugins);
|
||||
loadAvailablePlugins(listModel, nodes, installedSet);
|
||||
}
|
||||
|
||||
private static void fillListModel(DefaultListModel<BasePluginListNode> listModel,
|
||||
@@ -149,17 +152,14 @@ class PluginSettingsGroup implements ISettingsGroup {
|
||||
}
|
||||
|
||||
private void loadAvailablePlugins(DefaultListModel<BasePluginListNode> listModel,
|
||||
List<BasePluginListNode> nodes, List<PluginContext> installedPlugins) {
|
||||
List<BasePluginListNode> nodes, Set<String> installedSet) {
|
||||
mainWindow.getBackgroundExecutor().execute(
|
||||
NLS.str("preferences.plugins.task.downloading_list"),
|
||||
() -> {
|
||||
try {
|
||||
JadxPluginsList.getInstance().get(availablePlugins -> {
|
||||
Set<String> installed = installedPlugins.stream()
|
||||
.map(PluginContext::getPluginId)
|
||||
.collect(Collectors.toSet());
|
||||
List<AvailablePluginNode> availableNodes = availablePlugins.stream()
|
||||
.filter(availablePlugin -> !installed.contains(availablePlugin.getPluginId()))
|
||||
.filter(availablePlugin -> !installedSet.contains(availablePlugin.getPluginId()))
|
||||
.map(AvailablePluginNode::new)
|
||||
.collect(Collectors.toList());
|
||||
UiUtils.uiRunAndWait(() -> fillListModel(listModel, nodes, availableNodes));
|
||||
@@ -200,6 +200,17 @@ class PluginSettingsGroup implements ISettingsGroup {
|
||||
if (actionBtn != null) {
|
||||
top.add(actionBtn);
|
||||
}
|
||||
if (node.getAction() == PluginAction.UNINSTALL) {
|
||||
// TODO: allow disable bundled plugins
|
||||
boolean disabled = node.isDisabled();
|
||||
String statusChangeLabel = disabled
|
||||
? NLS.str("preferences.plugins.enable_btn")
|
||||
: NLS.str("preferences.plugins.disable_btn");
|
||||
JButton statusBtn = new JButton(statusChangeLabel);
|
||||
statusBtn.addActionListener(ev -> pluginsSettings.changeDisableStatus(node.getPluginId(), !disabled));
|
||||
top.add(Box.createHorizontalStrut(10));
|
||||
top.add(statusBtn);
|
||||
}
|
||||
|
||||
JPanel center = new JPanel();
|
||||
center.setLayout(new BoxLayout(center, BoxLayout.PAGE_AXIS));
|
||||
@@ -271,14 +282,19 @@ class PluginSettingsGroup implements ISettingsGroup {
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends BasePluginListNode> list,
|
||||
BasePluginListNode value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
if (!value.hasDetails()) {
|
||||
titleLbl.setText(value.getTitle());
|
||||
BasePluginListNode plugin, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
if (!plugin.hasDetails()) {
|
||||
titleLbl.setText(plugin.getTitle());
|
||||
return titleLbl;
|
||||
}
|
||||
nameLbl.setText(value.getTitle());
|
||||
nameLbl.setToolTipText(value.getLocationId());
|
||||
versionLbl.setText(Utils.getOrElse(value.getVersion(), ""));
|
||||
nameLbl.setText(plugin.getTitle());
|
||||
nameLbl.setToolTipText(plugin.getLocationId());
|
||||
versionLbl.setText(Utils.getOrElse(plugin.getVersion(), ""));
|
||||
|
||||
boolean enabled = !plugin.isDisabled();
|
||||
nameLbl.setEnabled(enabled);
|
||||
versionLbl.setEnabled(enabled);
|
||||
|
||||
if (isSelected) {
|
||||
panel.setBackground(list.getSelectionBackground());
|
||||
nameLbl.setBackground(list.getSelectionBackground());
|
||||
|
||||
@@ -77,17 +77,15 @@ import org.slf4j.LoggerFactory;
|
||||
import ch.qos.logback.classic.Level;
|
||||
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JadxDecompiler;
|
||||
import jadx.api.JavaClass;
|
||||
import jadx.api.JavaNode;
|
||||
import jadx.api.ResourceFile;
|
||||
import jadx.api.plugins.events.IJadxEvents;
|
||||
import jadx.api.plugins.events.JadxEvents;
|
||||
import jadx.api.plugins.events.types.ReloadProject;
|
||||
import jadx.api.plugins.events.types.ReloadSettingsWindow;
|
||||
import jadx.api.plugins.utils.CommonFileUtils;
|
||||
import jadx.core.Jadx;
|
||||
import jadx.core.export.TemplateFile;
|
||||
import jadx.core.plugins.events.JadxEventsImpl;
|
||||
import jadx.core.utils.ListUtils;
|
||||
import jadx.core.utils.StringUtils;
|
||||
import jadx.core.utils.android.AndroidManifestParser;
|
||||
@@ -99,6 +97,7 @@ import jadx.gui.JadxWrapper;
|
||||
import jadx.gui.cache.manager.CacheManager;
|
||||
import jadx.gui.device.debugger.BreakpointManager;
|
||||
import jadx.gui.events.services.RenameService;
|
||||
import jadx.gui.events.types.JadxGuiEventsImpl;
|
||||
import jadx.gui.jobs.BackgroundExecutor;
|
||||
import jadx.gui.jobs.DecompileTask;
|
||||
import jadx.gui.jobs.ExportTask;
|
||||
@@ -195,6 +194,7 @@ public class MainWindow extends JFrame {
|
||||
private final transient CacheObject cacheObject;
|
||||
private final transient CacheManager cacheManager;
|
||||
private final transient BackgroundExecutor backgroundExecutor;
|
||||
private final transient JadxGuiEventsImpl events = new JadxGuiEventsImpl();
|
||||
|
||||
private final TabsController tabsController;
|
||||
private final NavigationController navController;
|
||||
@@ -271,6 +271,7 @@ public class MainWindow extends JFrame {
|
||||
UiUtils.setWindowIcons(this);
|
||||
this.shortcutsController.registerMouseEventListener(this);
|
||||
loadSettings();
|
||||
initEvents();
|
||||
|
||||
update();
|
||||
checkForUpdate();
|
||||
@@ -500,9 +501,10 @@ public class MainWindow extends JFrame {
|
||||
synchronized (ReloadProject.EVENT) {
|
||||
saveAll();
|
||||
closeAll();
|
||||
loadFiles(UiUtils.EMPTY_RUNNABLE);
|
||||
|
||||
menuBar.reloadShortcuts();
|
||||
loadFiles(() -> {
|
||||
menuBar.reloadShortcuts();
|
||||
events().send(ReloadSettingsWindow.INSTANCE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,6 +527,7 @@ public class MainWindow extends JFrame {
|
||||
private void loadFiles(Runnable onFinish) {
|
||||
if (project.getFilePaths().isEmpty()) {
|
||||
tabsController.selectTab(new StartPageNode());
|
||||
onFinish.run();
|
||||
return;
|
||||
}
|
||||
AtomicReference<Exception> wrapperException = new AtomicReference<>();
|
||||
@@ -605,7 +608,6 @@ public class MainWindow extends JFrame {
|
||||
initTree();
|
||||
updateLiveReload(project.isEnableLiveReload());
|
||||
BreakpointManager.init(project.getFilePaths().get(0).toAbsolutePath().getParent());
|
||||
initEvents();
|
||||
|
||||
List<EditorViewState> openTabs = project.getOpenTabs(this);
|
||||
backgroundExecutor.execute(NLS.str("progress.load"),
|
||||
@@ -619,13 +621,12 @@ public class MainWindow extends JFrame {
|
||||
}
|
||||
|
||||
public void passesReloaded() {
|
||||
initEvents(); // TODO: events reset on reload passes on script run
|
||||
tabbedPane.reloadInactiveTabs();
|
||||
reloadTree();
|
||||
}
|
||||
|
||||
private void initEvents() {
|
||||
events().addListener(JadxEvents.RELOAD_PROJECT, ev -> UiUtils.uiRun(this::reopen));
|
||||
events().global().addListener(JadxEvents.RELOAD_PROJECT, ev -> UiUtils.uiRun(this::reopen));
|
||||
RenameService.init(this);
|
||||
}
|
||||
|
||||
@@ -1753,14 +1754,7 @@ public class MainWindow extends JFrame {
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Events instance if decompiler not yet available
|
||||
*/
|
||||
private final IJadxEvents fallbackEvents = new JadxEventsImpl();
|
||||
|
||||
public IJadxEvents events() {
|
||||
return wrapper.getCurrentDecompiler()
|
||||
.map(JadxDecompiler::events)
|
||||
.orElse(fallbackEvents);
|
||||
public JadxGuiEventsImpl events() {
|
||||
return events;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
#preferences.plugins.install=Install plugin
|
||||
#preferences.plugins.install_btn=Install
|
||||
#preferences.plugins.uninstall_btn=Uninstall
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
#preferences.plugins.location_id_label=Location id:
|
||||
#preferences.plugins.plugin_jar=Select Plugin jar
|
||||
#preferences.plugins.plugin_jar_label=or
|
||||
@@ -268,6 +270,7 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
#preferences.plugins.task.uninstalling=Uninstalling plugin
|
||||
#preferences.plugins.task.updating=Updating plugins
|
||||
#preferences.plugins.task.downloading_list=Downloading plugins list
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
#preferences.cache=Cache
|
||||
#preferences.cache.location=Cache location
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
preferences.plugins.install=Install plugin
|
||||
preferences.plugins.install_btn=Install
|
||||
preferences.plugins.uninstall_btn=Uninstall
|
||||
preferences.plugins.disable_btn=Disable
|
||||
preferences.plugins.enable_btn=Enable
|
||||
preferences.plugins.location_id_label=Location id:
|
||||
preferences.plugins.plugin_jar=Select Plugin jar
|
||||
preferences.plugins.plugin_jar_label=or
|
||||
@@ -268,6 +270,7 @@ preferences.plugins.task.installing=Installing plugin
|
||||
preferences.plugins.task.uninstalling=Uninstalling plugin
|
||||
preferences.plugins.task.updating=Updating plugins
|
||||
preferences.plugins.task.downloading_list=Downloading plugins list
|
||||
preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
preferences.cache=Cache
|
||||
preferences.cache.location=Cache location
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.rename_use_source_name_as_class_name_alias=Usar el nombre del source
|
||||
#preferences.plugins.install=Install plugin
|
||||
#preferences.plugins.install_btn=Install
|
||||
#preferences.plugins.uninstall_btn=Uninstall
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
#preferences.plugins.location_id_label=Location id:
|
||||
#preferences.plugins.plugin_jar=Select Plugin jar
|
||||
#preferences.plugins.plugin_jar_label=or
|
||||
@@ -268,6 +270,7 @@ preferences.rename_use_source_name_as_class_name_alias=Usar el nombre del source
|
||||
#preferences.plugins.task.uninstalling=Uninstalling plugin
|
||||
#preferences.plugins.task.updating=Updating plugins
|
||||
#preferences.plugins.task.downloading_list=Downloading plugins list
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
#preferences.cache=Cache
|
||||
#preferences.cache.location=Cache location
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
preferences.plugins.install=Instal plugin
|
||||
preferences.plugins.install_btn=Instal
|
||||
preferences.plugins.uninstall_btn=Uninstal
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
preferences.plugins.location_id_label=Lokasi id:
|
||||
preferences.plugins.plugin_jar=Pilih berkas jar Plugin
|
||||
preferences.plugins.plugin_jar_label=atau
|
||||
@@ -268,6 +270,7 @@ preferences.plugins.task.installing=Menginstal plugin
|
||||
preferences.plugins.task.uninstalling=Menguninstal plugin
|
||||
preferences.plugins.task.updating=Mengperbarui plugin
|
||||
preferences.plugins.task.downloading_list=Mengunduh daftar plugin
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
preferences.cache=Cache
|
||||
preferences.cache.location=Lokasi cache
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
#preferences.plugins.install=Install plugin
|
||||
#preferences.plugins.install_btn=Install
|
||||
#preferences.plugins.uninstall_btn=Uninstall
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
#preferences.plugins.location_id_label=Location id:
|
||||
#preferences.plugins.plugin_jar=Select Plugin jar
|
||||
#preferences.plugins.plugin_jar_label=or
|
||||
@@ -268,6 +270,7 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
#preferences.plugins.task.uninstalling=Uninstalling plugin
|
||||
#preferences.plugins.task.updating=Updating plugins
|
||||
#preferences.plugins.task.downloading_list=Downloading plugins list
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
#preferences.cache=Cache
|
||||
#preferences.cache.location=Cache location
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
#preferences.plugins.install=Install plugin
|
||||
#preferences.plugins.install_btn=Install
|
||||
#preferences.plugins.uninstall_btn=Uninstall
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
#preferences.plugins.location_id_label=Location id:
|
||||
#preferences.plugins.plugin_jar=Select Plugin jar
|
||||
#preferences.plugins.plugin_jar_label=or
|
||||
@@ -268,6 +270,7 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
#preferences.plugins.task.uninstalling=Uninstalling plugin
|
||||
#preferences.plugins.task.updating=Updating plugins
|
||||
#preferences.plugins.task.downloading_list=Downloading plugins list
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
#preferences.cache=Cache
|
||||
#preferences.cache.location=Cache location
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
preferences.plugins.install=Установить плагин
|
||||
preferences.plugins.install_btn=Установить
|
||||
preferences.plugins.uninstall_btn=Удалить
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
preferences.plugins.location_id_label=ID источика:
|
||||
preferences.plugins.plugin_jar=Выберите jar-файл плагина
|
||||
preferences.plugins.plugin_jar_label=или
|
||||
@@ -268,6 +270,7 @@ preferences.plugins.task.installing=Установка плагина
|
||||
preferences.plugins.task.uninstalling=Удаление плагина
|
||||
preferences.plugins.task.updating=Обновление плагинов
|
||||
preferences.plugins.task.downloading_list=Загрузка списка плагинов
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
preferences.cache=Кэш
|
||||
preferences.cache.location=Директория кэша
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=拖拽选项卡外观
|
||||
preferences.plugins.install=安装插件
|
||||
preferences.plugins.install_btn=安装
|
||||
preferences.plugins.uninstall_btn=卸载
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
preferences.plugins.location_id_label=位置ID:
|
||||
preferences.plugins.plugin_jar=选择插件 jar
|
||||
preferences.plugins.plugin_jar_label=或
|
||||
@@ -268,6 +270,7 @@ preferences.plugins.task.installing=安装插件中
|
||||
preferences.plugins.task.uninstalling=卸载插件中
|
||||
preferences.plugins.task.updating=更新插件中
|
||||
preferences.plugins.task.downloading_list=正在下载插件列表
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
preferences.cache=缓存
|
||||
preferences.cache.location=缓存位置
|
||||
|
||||
@@ -259,6 +259,8 @@ preferences.tab_dnd_appearance=Dragging tab appearance
|
||||
preferences.plugins.install=安裝外掛程式
|
||||
preferences.plugins.install_btn=安裝
|
||||
preferences.plugins.uninstall_btn=解除安裝
|
||||
#preferences.plugins.disable_btn=Disable
|
||||
#preferences.plugins.enable_btn=Enable
|
||||
preferences.plugins.location_id_label=位置 id:
|
||||
preferences.plugins.plugin_jar=選擇外掛程式 jar
|
||||
preferences.plugins.plugin_jar_label=或
|
||||
@@ -268,6 +270,7 @@ preferences.plugins.task.installing=正在安裝外掛程式
|
||||
preferences.plugins.task.uninstalling=正在解除安裝外掛程式
|
||||
preferences.plugins.task.updating=正在更新外掛程式
|
||||
preferences.plugins.task.downloading_list=正在下載外掛程式列表
|
||||
#preferences.plugins.task.status=Changing plugin status
|
||||
|
||||
preferences.cache=快取
|
||||
preferences.cache.location=快取位置
|
||||
|
||||
@@ -72,7 +72,7 @@ public class JadxExternalPluginsLoader implements JadxPluginLoader {
|
||||
}
|
||||
|
||||
private void loadInstalledPlugins(Map<Class<? extends JadxPlugin>, JadxPlugin> map, ClassLoader classLoader) {
|
||||
List<Path> jars = JadxPluginsTools.getInstance().getAllPluginJars();
|
||||
List<Path> jars = JadxPluginsTools.getInstance().getEnabledPluginJars();
|
||||
for (Path jar : jars) {
|
||||
classLoaders.add(loadFromJar(map, classLoader, jar));
|
||||
}
|
||||
|
||||
@@ -28,9 +28,6 @@ import jadx.plugins.tools.utils.PluginUtils;
|
||||
|
||||
import static jadx.plugins.tools.utils.PluginFiles.PLUGINS_LIST_CACHE;
|
||||
|
||||
/**
|
||||
* TODO: implement list caching (on disk) with check for new release
|
||||
*/
|
||||
public class JadxPluginsList {
|
||||
private static final JadxPluginsList INSTANCE = new JadxPluginsList();
|
||||
|
||||
|
||||
@@ -124,6 +124,38 @@ public class JadxPluginsTools {
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<Path> getEnabledPluginJars() {
|
||||
List<Path> list = new ArrayList<>();
|
||||
for (JadxPluginMetadata pluginMetadata : loadPluginsJson().getInstalled()) {
|
||||
if (pluginMetadata.isDisabled()) {
|
||||
continue;
|
||||
}
|
||||
list.add(INSTALLED_DIR.resolve(pluginMetadata.getJar()));
|
||||
}
|
||||
collectFromDir(list, DROPINS_DIR);
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable or enable plugin
|
||||
*
|
||||
* @return true if disabled status was changed
|
||||
*/
|
||||
public boolean changeDisabledStatus(String pluginId, boolean disabled) {
|
||||
JadxInstalledPlugins data = loadPluginsJson();
|
||||
JadxPluginMetadata plugin = data.getInstalled().stream()
|
||||
.filter(p -> p.getPluginId().equals(pluginId))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException("Plugin not found: " + pluginId));
|
||||
if (plugin.isDisabled() == disabled) {
|
||||
return false;
|
||||
}
|
||||
plugin.setDisabled(disabled);
|
||||
data.setUpdated(System.currentTimeMillis());
|
||||
savePluginsJson(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
private @Nullable JadxPluginMetadata update(JadxPluginMetadata plugin) {
|
||||
IJadxPluginResolver resolver = ResolversRegistry.getById(plugin.getResolverId());
|
||||
if (!resolver.isUpdateSupported()) {
|
||||
|
||||
@@ -12,6 +12,7 @@ public class JadxPluginMetadata implements Comparable<JadxPluginMetadata> {
|
||||
private String locationId;
|
||||
private String resolverId;
|
||||
private String jar;
|
||||
private boolean disabled;
|
||||
|
||||
public String getPluginId() {
|
||||
return pluginId;
|
||||
@@ -77,6 +78,14 @@ public class JadxPluginMetadata implements Comparable<JadxPluginMetadata> {
|
||||
this.jar = jar;
|
||||
}
|
||||
|
||||
public boolean isDisabled() {
|
||||
return disabled;
|
||||
}
|
||||
|
||||
public void setDisabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
|
||||
Reference in New Issue
Block a user