feat(plugins): get config and cache dirs for plugins

This commit is contained in:
Skylot
2024-09-28 22:37:31 +01:00
parent 90185fd947
commit b26abdc851
15 changed files with 231 additions and 19 deletions
+1
View File
@@ -9,6 +9,7 @@ plugins {
dependencies {
implementation(project(":jadx-core"))
implementation(project(":jadx-plugins-tools"))
implementation(project(":jadx-commons:jadx-app-commons"))
runtimeOnly(project(":jadx-plugins:jadx-dex-input"))
runtimeOnly(project(":jadx-plugins:jadx-java-input"))
@@ -9,6 +9,7 @@ import jadx.api.impl.AnnotatedCodeWriter;
import jadx.api.impl.NoOpCodeCache;
import jadx.api.impl.SimpleCodeWriter;
import jadx.cli.LogHelper.LogLevelEnum;
import jadx.cli.plugins.JadxFilesGetter;
import jadx.core.utils.exceptions.JadxArgsValidateException;
import jadx.core.utils.files.FileUtils;
import jadx.plugins.tools.JadxExternalPluginsLoader;
@@ -46,6 +47,7 @@ public class JadxCLI {
JadxArgs jadxArgs = cliArgs.toJadxArgs();
jadxArgs.setCodeCache(new NoOpCodeCache());
jadxArgs.setPluginLoader(new JadxExternalPluginsLoader());
jadxArgs.setFilesGetter(JadxFilesGetter.INSTANCE);
initCodeWriterProvider(jadxArgs);
try (JadxDecompiler jadx = new JadxDecompiler(jadxArgs)) {
jadx.load();
@@ -0,0 +1,31 @@
package jadx.cli.plugins;
import java.nio.file.Path;
import jadx.commons.app.JadxCommonFiles;
import jadx.core.plugins.files.IJadxFilesGetter;
import jadx.core.utils.files.FileUtils;
public class JadxFilesGetter implements IJadxFilesGetter {
public static final JadxFilesGetter INSTANCE = new JadxFilesGetter();
@Override
public Path getConfigDir() {
return JadxCommonFiles.getConfigDir();
}
@Override
public Path getCacheDir() {
return JadxCommonFiles.getCacheDir();
}
@Override
public Path getTempDir() {
return FileUtils.getTempRootDir();
}
private JadxFilesGetter() {
// singleton
}
}
@@ -36,6 +36,8 @@ import jadx.core.deobf.DeobfAliasProvider;
import jadx.core.deobf.conditions.DeobfWhitelist;
import jadx.core.deobf.conditions.JadxRenameConditions;
import jadx.core.plugins.PluginContext;
import jadx.core.plugins.files.IJadxFilesGetter;
import jadx.core.plugins.files.TempFilesGetter;
import jadx.core.utils.files.FileUtils;
public class JadxArgs implements Closeable {
@@ -166,6 +168,12 @@ public class JadxArgs implements Closeable {
private UseKotlinMethodsForVarNames useKotlinMethodsForVarNames = UseKotlinMethodsForVarNames.APPLY;
/**
* Additional files structure info.
* Defaults to tmp dirs.
*/
private IJadxFilesGetter filesGetter = TempFilesGetter.INSTANCE;
/**
* Don't save files (can be using for performance testing)
*/
@@ -710,6 +718,14 @@ public class JadxArgs implements Closeable {
this.useKotlinMethodsForVarNames = useKotlinMethodsForVarNames;
}
public IJadxFilesGetter getFilesGetter() {
return filesGetter;
}
public void setFilesGetter(IJadxFilesGetter filesGetter) {
this.filesGetter = filesGetter;
}
public boolean isSkipFilesSave() {
return skipFilesSave;
}
@@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.api.plugins.data.IJadxFiles;
import jadx.api.plugins.data.IJadxPlugins;
import jadx.api.plugins.events.IJadxEvents;
import jadx.api.plugins.gui.JadxGuiContext;
@@ -53,4 +54,9 @@ public interface JadxPluginContext {
* Access to registered plugins and runtime data
*/
IJadxPlugins plugins();
/**
* Access to plugin specific files and directories
*/
IJadxFiles files();
}
@@ -0,0 +1,21 @@
package jadx.api.plugins.data;
import java.nio.file.Path;
public interface IJadxFiles {
/**
* Plugin cache directory.
*/
Path getPluginCacheDir();
/**
* Plugin config directory.
*/
Path getPluginConfigDir();
/**
* Plugin temp directory.
*/
Path getPluginTempDir();
}
@@ -0,0 +1,31 @@
package jadx.core.plugins;
import java.util.Objects;
import org.jetbrains.annotations.Nullable;
import jadx.api.plugins.gui.JadxGuiContext;
import jadx.core.plugins.files.IJadxFilesGetter;
public class AppContext {
private @Nullable JadxGuiContext guiContext;
private IJadxFilesGetter filesGetter;
public @Nullable JadxGuiContext getGuiContext() {
return guiContext;
}
public void setGuiContext(@Nullable JadxGuiContext guiContext) {
this.guiContext = guiContext;
}
public IJadxFilesGetter getFilesGetter() {
return Objects.requireNonNull(filesGetter);
}
public void setFilesGetter(IJadxFilesGetter filesGetter) {
this.filesGetter = filesGetter;
}
}
@@ -122,8 +122,12 @@ public class JadxPluginManager {
}
public void init(SortedSet<PluginContext> pluginContexts) {
AppContext defAppContext = buildDefaultAppContext();
for (PluginContext context : pluginContexts) {
try {
if (context.getAppContext() == null) {
context.setAppContext(defAppContext);
}
context.init();
} catch (Exception e) {
throw new JadxRuntimeException("Failed to init plugin: " + context.getPluginId(), e);
@@ -137,6 +141,13 @@ public class JadxPluginManager {
}
}
private AppContext buildDefaultAppContext() {
AppContext appContext = new AppContext();
appContext.setGuiContext(null);
appContext.setFilesGetter(decompiler.getArgs().getFilesGetter());
return appContext;
}
private void verifyOptions(PluginContext pluginContext, JadxPluginOptions options) {
String pluginId = pluginContext.getPluginId();
List<OptionDescription> descriptions = options.getOptionsDescriptions();
@@ -15,6 +15,7 @@ import jadx.api.JadxDecompiler;
import jadx.api.plugins.JadxPlugin;
import jadx.api.plugins.JadxPluginContext;
import jadx.api.plugins.JadxPluginInfo;
import jadx.api.plugins.data.IJadxFiles;
import jadx.api.plugins.data.IJadxPlugins;
import jadx.api.plugins.data.JadxPluginRuntimeData;
import jadx.api.plugins.events.IJadxEvents;
@@ -27,6 +28,7 @@ import jadx.api.plugins.options.OptionDescription;
import jadx.api.plugins.options.OptionFlag;
import jadx.api.plugins.pass.JadxPass;
import jadx.api.plugins.resources.IResourcesLoader;
import jadx.core.plugins.files.JadxFilesData;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.core.utils.files.FileUtils;
@@ -36,7 +38,8 @@ public class PluginContext implements JadxPluginContext, JadxPluginRuntimeData,
private final JadxPluginsData pluginsData;
private final JadxPlugin plugin;
private final JadxPluginInfo pluginInfo;
private @Nullable JadxGuiContext guiContext;
private AppContext appContext;
private final List<JadxCodeInput> codeInputs = new ArrayList<>();
private @Nullable JadxPluginOptions options;
@@ -137,13 +140,17 @@ public class PluginContext implements JadxPluginContext, JadxPluginRuntimeData,
return decompiler.getResourcesLoader();
}
@Override
public @Nullable JadxGuiContext getGuiContext() {
return guiContext;
public AppContext getAppContext() {
return appContext;
}
public void setGuiContext(JadxGuiContext guiContext) {
this.guiContext = guiContext;
public void setAppContext(AppContext appContext) {
this.appContext = appContext;
}
@Override
public @Nullable JadxGuiContext getGuiContext() {
return appContext.getGuiContext();
}
@Override
@@ -171,6 +178,11 @@ public class PluginContext implements JadxPluginContext, JadxPluginRuntimeData,
return pluginsData;
}
@Override
public IJadxFiles files() {
return new JadxFilesData(pluginInfo, appContext.getFilesGetter());
}
@Override
public ICodeLoader loadCodeFiles(List<Path> files, @Nullable Closeable closeable) {
return new MergeCodeLoader(
@@ -0,0 +1,12 @@
package jadx.core.plugins.files;
import java.nio.file.Path;
public interface IJadxFilesGetter {
Path getConfigDir();
Path getCacheDir();
Path getTempDir();
}
@@ -0,0 +1,37 @@
package jadx.core.plugins.files;
import java.nio.file.Path;
import jadx.api.plugins.JadxPluginInfo;
import jadx.api.plugins.data.IJadxFiles;
public class JadxFilesData implements IJadxFiles {
private static final String PLUGINS_DATA_DIR = "plugins-data";
private final JadxPluginInfo pluginInfo;
private final IJadxFilesGetter filesGetter;
public JadxFilesData(JadxPluginInfo pluginInfo, IJadxFilesGetter filesGetter) {
this.pluginInfo = pluginInfo;
this.filesGetter = filesGetter;
}
@Override
public Path getPluginCacheDir() {
return toPluginPath(filesGetter.getCacheDir());
}
@Override
public Path getPluginConfigDir() {
return toPluginPath(filesGetter.getConfigDir());
}
@Override
public Path getPluginTempDir() {
return toPluginPath(filesGetter.getTempDir());
}
private Path toPluginPath(Path dir) {
return dir.resolve(PLUGINS_DATA_DIR).resolve(pluginInfo.getPluginId());
}
}
@@ -0,0 +1,29 @@
package jadx.core.plugins.files;
import java.nio.file.Path;
import jadx.core.utils.files.FileUtils;
public class TempFilesGetter implements IJadxFilesGetter {
public static final TempFilesGetter INSTANCE = new TempFilesGetter();
@Override
public Path getConfigDir() {
return FileUtils.getTempRootDir().resolve("config");
}
@Override
public Path getCacheDir() {
return FileUtils.getTempRootDir().resolve("cache");
}
@Override
public Path getTempDir() {
return FileUtils.getTempRootDir().resolve("temp");
}
private TempFilesGetter() {
// singleton
}
}
@@ -168,6 +168,10 @@ public class FileUtils {
}
}
public static Path getTempRootDir() {
return TEMP_ROOT_DIR;
}
public static void deleteTempRootDir() {
deleteDirIfExists(TEMP_ROOT_DIR);
}
@@ -23,16 +23,17 @@ import jadx.api.impl.InMemoryCodeCache;
import jadx.api.metadata.ICodeNodeRef;
import jadx.api.usage.impl.EmptyUsageInfoCache;
import jadx.api.usage.impl.InMemoryUsageInfoCache;
import jadx.cli.plugins.JadxFilesGetter;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.ProcessState;
import jadx.core.dex.nodes.RootNode;
import jadx.core.plugins.AppContext;
import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.cache.code.CodeStringCache;
import jadx.gui.cache.code.disk.BufferCodeCache;
import jadx.gui.cache.code.disk.DiskCodeCache;
import jadx.gui.cache.usage.UsageInfoCache;
import jadx.gui.plugins.context.CommonGuiPluginsContext;
import jadx.gui.plugins.context.GuiPluginContext;
import jadx.gui.settings.JadxProject;
import jadx.gui.settings.JadxSettings;
import jadx.gui.ui.MainWindow;
@@ -67,7 +68,7 @@ public class JadxWrapper {
project.fillJadxArgs(jadxArgs);
decompiler = new JadxDecompiler(jadxArgs);
initGuiPluginsContext();
guiPluginsContext = initGuiPluginsContext(decompiler, mainWindow);
initUsageCache(jadxArgs);
decompiler.load();
initCodeCache();
@@ -139,12 +140,15 @@ public class JadxWrapper {
}
}
private void initGuiPluginsContext() {
guiPluginsContext = new CommonGuiPluginsContext(mainWindow);
public static CommonGuiPluginsContext initGuiPluginsContext(JadxDecompiler decompiler, MainWindow mainWindow) {
CommonGuiPluginsContext guiPluginsContext = new CommonGuiPluginsContext(mainWindow);
decompiler.getPluginManager().registerAddPluginListener(pluginContext -> {
GuiPluginContext guiContext = guiPluginsContext.buildForPlugin(pluginContext);
pluginContext.setGuiContext(guiContext);
AppContext appContext = new AppContext();
appContext.setGuiContext(guiPluginsContext.buildForPlugin(pluginContext));
appContext.setFilesGetter(JadxFilesGetter.INSTANCE);
pluginContext.setAppContext(appContext);
});
return guiPluginsContext;
}
public CommonGuiPluginsContext getGuiPluginsContext() {
@@ -9,8 +9,7 @@ import jadx.api.JadxArgs;
import jadx.api.JadxDecompiler;
import jadx.core.plugins.JadxPluginManager;
import jadx.core.plugins.PluginContext;
import jadx.gui.plugins.context.CommonGuiPluginsContext;
import jadx.gui.plugins.context.GuiPluginContext;
import jadx.gui.JadxWrapper;
import jadx.gui.ui.MainWindow;
import jadx.plugins.tools.JadxExternalPluginsLoader;
@@ -36,11 +35,7 @@ public class CollectPlugins {
try (JadxDecompiler decompiler = new JadxDecompiler(new JadxArgs())) {
JadxPluginManager pluginManager = decompiler.getPluginManager();
pluginManager.load(new JadxExternalPluginsLoader());
CommonGuiPluginsContext guiPluginsContext = new CommonGuiPluginsContext(mainWindow);
decompiler.getPluginManager().registerAddPluginListener(pluginContext -> {
GuiPluginContext guiContext = guiPluginsContext.buildForPlugin(pluginContext);
pluginContext.setGuiContext(guiContext);
});
JadxWrapper.initGuiPluginsContext(decompiler, mainWindow);
SortedSet<PluginContext> missingPlugins = new TreeSet<>();
for (PluginContext context : pluginManager.getAllPluginContexts()) {
if (!allPlugins.contains(context)) {