feat(plugins): allow to use .zip as plugin artifact (with jars inside)
This commit is contained in:
@@ -27,6 +27,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -78,6 +79,22 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Path> listFiles(Path dir) {
|
||||
try (Stream<Path> files = Files.list(dir)) {
|
||||
return files.collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
throw new JadxRuntimeException("Failed to list files in directory: " + dir, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Path> listFiles(Path dir, Predicate<? super Path> filter) {
|
||||
try (Stream<Path> files = Files.list(dir)) {
|
||||
return files.filter(filter).collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
throw new JadxRuntimeException("Failed to list files in directory: " + dir, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Path> expandDirs(List<Path> paths) {
|
||||
List<Path> files = new ArrayList<>(paths.size());
|
||||
for (Path path : paths) {
|
||||
@@ -148,6 +165,10 @@ public class FileUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void deleteDir(Path dir) {
|
||||
deleteDir(dir, false);
|
||||
}
|
||||
|
||||
public static void deleteDirIfExists(Path dir) {
|
||||
if (Files.exists(dir)) {
|
||||
try {
|
||||
@@ -158,10 +179,6 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteDir(Path dir) {
|
||||
deleteDir(dir, false);
|
||||
}
|
||||
|
||||
private static void deleteDir(Path dir, boolean keepRootDir) {
|
||||
try {
|
||||
List<Path> files = new ArrayList<>();
|
||||
@@ -424,6 +441,11 @@ public class FileUtils {
|
||||
return fileName.substring(0, extEndIndex);
|
||||
}
|
||||
|
||||
public static boolean hasExtension(Path path, String extension) {
|
||||
String fileName = path.getFileName().toString();
|
||||
return fileName.toLowerCase().endsWith(extension);
|
||||
}
|
||||
|
||||
public static File toFile(String path) {
|
||||
if (path == null) {
|
||||
return null;
|
||||
|
||||
@@ -3,7 +3,6 @@ package jadx.gui.settings.ui.plugins;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
@@ -61,7 +60,7 @@ public class InstallPluginDialog extends JDialog {
|
||||
locationPanel.add(locationFld);
|
||||
|
||||
JButton fileBtn = new JButton(NLS.str("preferences.plugins.plugin_jar"));
|
||||
fileBtn.addActionListener(ev -> openPluginJar());
|
||||
fileBtn.addActionListener(ev -> openPluginFile());
|
||||
JLabel fileLbl = new JLabel(NLS.str("preferences.plugins.plugin_jar_label"));
|
||||
fileLbl.setLabelFor(fileBtn);
|
||||
|
||||
@@ -105,10 +104,10 @@ public class InstallPluginDialog extends JDialog {
|
||||
UiUtils.addEscapeShortCutToDispose(this);
|
||||
}
|
||||
|
||||
private void openPluginJar() {
|
||||
private void openPluginFile() {
|
||||
FileDialogWrapper fd = new FileDialogWrapper(mainWindow, FileOpenMode.CUSTOM_OPEN);
|
||||
fd.setTitle(NLS.str("preferences.plugins.plugin_jar"));
|
||||
fd.setFileExtList(Collections.singletonList("jar"));
|
||||
fd.setFileExtList(List.of("jar", "zip"));
|
||||
fd.setSelectionMode(JFileChooser.FILES_ONLY);
|
||||
List<Path> files = fd.show();
|
||||
if (files.size() == 1) {
|
||||
|
||||
@@ -9,6 +9,7 @@ dependencies {
|
||||
implementation(project(":jadx-commons:jadx-app-commons"))
|
||||
|
||||
implementation("com.google.code.gson:gson:2.13.2")
|
||||
implementation("commons-io:commons-io:2.21.0")
|
||||
|
||||
testImplementation("com.squareup.okhttp3:mockwebserver3:5.3.0")
|
||||
}
|
||||
|
||||
+39
-13
@@ -1,8 +1,9 @@
|
||||
package jadx.plugins.tools;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@@ -19,6 +20,7 @@ import jadx.api.plugins.JadxPlugin;
|
||||
import jadx.api.plugins.loader.JadxPluginLoader;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
|
||||
public class JadxExternalPluginsLoader implements JadxPluginLoader {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JadxExternalPluginsLoader.class);
|
||||
@@ -44,16 +46,16 @@ public class JadxExternalPluginsLoader implements JadxPluginLoader {
|
||||
return list;
|
||||
}
|
||||
|
||||
public JadxPlugin loadFromJar(Path jar) {
|
||||
public JadxPlugin loadFromPath(Path pluginPath) {
|
||||
Map<String, JadxPlugin> map = new HashMap<>();
|
||||
loadFromJar(map, jar);
|
||||
loadFromPath(map, pluginPath);
|
||||
int loaded = map.size();
|
||||
if (loaded == 0) {
|
||||
throw new JadxRuntimeException("No plugin found in jar: " + jar);
|
||||
throw new JadxRuntimeException("No plugin found in jar: " + pluginPath);
|
||||
}
|
||||
if (loaded > 1) {
|
||||
String plugins = map.values().stream().map(p -> p.getPluginInfo().getPluginId()).collect(Collectors.joining(", "));
|
||||
throw new JadxRuntimeException("Expect only one plugin per jar: " + jar + ", but found: " + loaded + " - " + plugins);
|
||||
throw new JadxRuntimeException("Expect only one plugin per jar: " + pluginPath + ", but found: " + loaded + " - " + plugins);
|
||||
}
|
||||
return Utils.first(map.values());
|
||||
|
||||
@@ -72,22 +74,46 @@ public class JadxExternalPluginsLoader implements JadxPluginLoader {
|
||||
}
|
||||
|
||||
private void loadInstalledPlugins(Map<String, JadxPlugin> map) {
|
||||
List<Path> jars = JadxPluginsTools.getInstance().getEnabledPluginJars();
|
||||
for (Path jar : jars) {
|
||||
loadFromJar(map, jar);
|
||||
List<Path> paths = JadxPluginsTools.getInstance().getEnabledPluginPaths();
|
||||
for (Path pluginPath : paths) {
|
||||
loadFromPath(map, pluginPath);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadFromJar(Map<String, JadxPlugin> map, Path jar) {
|
||||
private void loadFromPath(Map<String, JadxPlugin> map, Path pluginPath) {
|
||||
try {
|
||||
File jarFile = jar.toFile();
|
||||
String clsLoaderName = JADX_PLUGIN_CLASSLOADER_PREFIX + jarFile.getName();
|
||||
URL[] urls = new URL[] { jarFile.toURI().toURL() };
|
||||
URL[] urls;
|
||||
if (Files.isDirectory(pluginPath)) {
|
||||
urls = FileUtils.listFiles(pluginPath, file -> FileUtils.hasExtension(file, ".jar"))
|
||||
.stream()
|
||||
.map(JadxExternalPluginsLoader::toURL)
|
||||
.toArray(URL[]::new);
|
||||
if (urls.length == 0) {
|
||||
throw new JadxRuntimeException("No jar files found in plugin directory");
|
||||
}
|
||||
} else if (Files.isRegularFile(pluginPath)) {
|
||||
if (FileUtils.hasExtension(pluginPath, ".jar")) {
|
||||
urls = new URL[] { toURL(pluginPath) };
|
||||
} else {
|
||||
throw new JadxRuntimeException("Unexpected plugin file format");
|
||||
}
|
||||
} else {
|
||||
throw new JadxRuntimeException("Plugin file not found");
|
||||
}
|
||||
String clsLoaderName = JADX_PLUGIN_CLASSLOADER_PREFIX + pluginPath.getFileName();
|
||||
URLClassLoader pluginClsLoader = new URLClassLoader(clsLoaderName, urls, thisClassLoader());
|
||||
classLoaders.add(pluginClsLoader);
|
||||
loadFromClsLoader(map, pluginClsLoader);
|
||||
} catch (Exception e) {
|
||||
throw new JadxRuntimeException("Failed to load plugins from jar: " + jar, e);
|
||||
throw new JadxRuntimeException("Failed to load plugins from: " + pluginPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static URL toURL(Path pluginPath) {
|
||||
try {
|
||||
return pluginPath.toUri().toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@@ -23,17 +22,22 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.plugins.JadxPlugin;
|
||||
import jadx.api.plugins.JadxPluginInfo;
|
||||
import jadx.api.plugins.utils.CommonFileUtils;
|
||||
import jadx.core.Jadx;
|
||||
import jadx.core.plugins.versions.VerifyRequiredVersion;
|
||||
import jadx.core.utils.StringUtils;
|
||||
import jadx.core.utils.Utils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
import jadx.plugins.tools.data.JadxInstalledPlugins;
|
||||
import jadx.plugins.tools.data.JadxPluginMetadata;
|
||||
import jadx.plugins.tools.data.JadxPluginUpdate;
|
||||
import jadx.plugins.tools.resolvers.IJadxPluginResolver;
|
||||
import jadx.plugins.tools.resolvers.ResolversRegistry;
|
||||
import jadx.plugins.tools.utils.PluginUtils;
|
||||
import jadx.zip.IZipEntry;
|
||||
import jadx.zip.ZipContent;
|
||||
import jadx.zip.ZipReader;
|
||||
|
||||
import static jadx.core.utils.GsonUtils.buildGson;
|
||||
import static jadx.plugins.tools.utils.PluginFiles.DROPINS_DIR;
|
||||
@@ -165,7 +169,7 @@ public class JadxPluginsTools {
|
||||
return false;
|
||||
}
|
||||
JadxPluginMetadata plugin = found.get();
|
||||
deletePluginJar(plugin);
|
||||
deletePlugin(plugin);
|
||||
plugins.getInstalled().remove(plugin);
|
||||
savePluginsJson(plugins);
|
||||
return true;
|
||||
@@ -189,24 +193,15 @@ public class JadxPluginsTools {
|
||||
}
|
||||
}
|
||||
|
||||
public List<Path> getAllPluginJars() {
|
||||
List<Path> list = new ArrayList<>();
|
||||
for (JadxPluginMetadata pluginMetadata : loadPluginsJson().getInstalled()) {
|
||||
list.add(INSTALLED_DIR.resolve(pluginMetadata.getJar()));
|
||||
}
|
||||
collectJarsFromDir(list, DROPINS_DIR);
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<Path> getEnabledPluginJars() {
|
||||
public List<Path> getEnabledPluginPaths() {
|
||||
List<Path> list = new ArrayList<>();
|
||||
for (JadxPluginMetadata pluginMetadata : loadPluginsJson().getInstalled()) {
|
||||
if (pluginMetadata.isDisabled()) {
|
||||
continue;
|
||||
}
|
||||
list.add(INSTALLED_DIR.resolve(pluginMetadata.getJar()));
|
||||
list.add(INSTALLED_DIR.resolve(pluginMetadata.getPath()));
|
||||
}
|
||||
collectJarsFromDir(list, DROPINS_DIR);
|
||||
list.addAll(FileUtils.listFiles(DROPINS_DIR));
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -254,22 +249,31 @@ public class JadxPluginsTools {
|
||||
throw new JadxRuntimeException("Can't install plugin, required version: \"" + reqVersionStr + '\"'
|
||||
+ " is not compatible with current jadx version: " + Jadx.getVersion());
|
||||
}
|
||||
// remove previous version
|
||||
uninstall(metadata.getPluginId());
|
||||
|
||||
String version = metadata.getVersion();
|
||||
String fileName = metadata.getPluginId() + (StringUtils.notBlank(version) ? '-' + version : "") + ".jar";
|
||||
Path pluginJar = INSTALLED_DIR.resolve(fileName);
|
||||
copyJar(Paths.get(metadata.getJar()), pluginJar);
|
||||
metadata.setJar(INSTALLED_DIR.relativize(pluginJar).toString());
|
||||
|
||||
JadxInstalledPlugins plugins = loadPluginsJson();
|
||||
// remove previous version jar
|
||||
plugins.getInstalled().removeIf(p -> {
|
||||
if (p.getPluginId().equals(metadata.getPluginId())) {
|
||||
deletePluginJar(p);
|
||||
return true;
|
||||
String pluginBaseName = metadata.getPluginId() + (StringUtils.notBlank(version) ? '-' + version : "");
|
||||
String pluginPathStr = metadata.getPath();
|
||||
Path pluginPath = Paths.get(pluginPathStr);
|
||||
if (pluginPathStr.endsWith(".jar")) {
|
||||
Path pluginJar = INSTALLED_DIR.resolve(pluginBaseName + ".jar");
|
||||
copyJar(pluginPath, pluginJar);
|
||||
metadata.setPath(INSTALLED_DIR.relativize(pluginJar).toString());
|
||||
} else if (Files.isDirectory(pluginPath)) {
|
||||
Path pluginDir = INSTALLED_DIR.resolve(pluginBaseName);
|
||||
try {
|
||||
FileUtils.deleteDirIfExists(pluginDir);
|
||||
org.apache.commons.io.FileUtils.moveDirectory(pluginPath.toFile(), pluginDir.toFile());
|
||||
} catch (IOException e) {
|
||||
throw new JadxRuntimeException("Failed to install plugin: " + pluginBaseName, e);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
metadata.setPath(INSTALLED_DIR.relativize(pluginDir).toString());
|
||||
} else {
|
||||
throw new JadxRuntimeException("Unexpected plugin path type: " + pluginPathStr);
|
||||
}
|
||||
// update plugins json
|
||||
JadxInstalledPlugins plugins = loadPluginsJson();
|
||||
plugins.getInstalled().add(metadata);
|
||||
plugins.setUpdated(System.currentTimeMillis());
|
||||
savePluginsJson(plugins);
|
||||
@@ -277,23 +281,30 @@ public class JadxPluginsTools {
|
||||
|
||||
private void fillMetadata(JadxPluginMetadata metadata) {
|
||||
try {
|
||||
Path tmpJar;
|
||||
if (needDownload(metadata.getJar())) {
|
||||
tmpJar = Files.createTempFile(metadata.getName(), "plugin.jar");
|
||||
PluginUtils.downloadFile(metadata.getJar(), tmpJar);
|
||||
metadata.setJar(tmpJar.toAbsolutePath().toString());
|
||||
} else {
|
||||
tmpJar = Paths.get(metadata.getJar());
|
||||
String pluginPath = metadata.getPath();
|
||||
if (needDownload(pluginPath)) {
|
||||
// download plugin
|
||||
String ext = CommonFileUtils.getFileExtension(pluginPath);
|
||||
Path tmpJar = Files.createTempFile(metadata.getName(), "plugin." + ext);
|
||||
PluginUtils.downloadFile(pluginPath, tmpJar);
|
||||
pluginPath = tmpJar.toAbsolutePath().toString();
|
||||
}
|
||||
fillMetadataFromJar(metadata, tmpJar);
|
||||
if (pluginPath.endsWith(".zip")) {
|
||||
// unpack plugin zip
|
||||
Path tmpDir = Files.createTempDirectory(metadata.getName());
|
||||
unzip(Paths.get(pluginPath), tmpDir);
|
||||
pluginPath = tmpDir.toAbsolutePath().toString();
|
||||
}
|
||||
metadata.setPath(pluginPath);
|
||||
fillMetadataFromPath(metadata, Paths.get(pluginPath));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to fill plugin metadata, plugin: " + metadata.getPluginId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillMetadataFromJar(JadxPluginMetadata metadata, Path jar) {
|
||||
private void fillMetadataFromPath(JadxPluginMetadata metadata, Path pluginPath) {
|
||||
try (JadxExternalPluginsLoader loader = new JadxExternalPluginsLoader()) {
|
||||
JadxPlugin jadxPlugin = loader.loadFromJar(jar);
|
||||
JadxPlugin jadxPlugin = loader.loadFromPath(pluginPath);
|
||||
JadxPluginInfo pluginInfo = jadxPlugin.getPluginInfo();
|
||||
metadata.setPluginId(pluginInfo.getPluginId());
|
||||
metadata.setName(pluginInfo.getName());
|
||||
@@ -317,9 +328,14 @@ public class JadxPluginsTools {
|
||||
}
|
||||
}
|
||||
|
||||
private void deletePluginJar(JadxPluginMetadata plugin) {
|
||||
private void deletePlugin(JadxPluginMetadata plugin) {
|
||||
try {
|
||||
Files.deleteIfExists(INSTALLED_DIR.resolve(plugin.getJar()));
|
||||
Path pluginPath = INSTALLED_DIR.resolve(plugin.getPath());
|
||||
if (Files.isDirectory(pluginPath)) {
|
||||
FileUtils.deleteDir(pluginPath);
|
||||
} else {
|
||||
Files.deleteIfExists(pluginPath);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
@@ -363,11 +379,15 @@ public class JadxPluginsTools {
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectJarsFromDir(List<Path> list, Path dir) {
|
||||
try (Stream<Path> files = Files.list(dir)) {
|
||||
files.filter(p -> p.getFileName().toString().endsWith(".jar")).forEach(list::add);
|
||||
private static void unzip(Path zipFile, Path outDir) {
|
||||
ZipReader zipReader = new ZipReader(); // TODO: pass zip options from jadx args
|
||||
try (ZipContent content = zipReader.open(zipFile.toFile())) {
|
||||
for (IZipEntry entry : content.getEntries()) {
|
||||
Path entryFile = outDir.resolve(entry.getName());
|
||||
Files.copy(entry.getInputStream(), entryFile, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new JadxRuntimeException("Failed to unzip file: " + zipFile, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package jadx.plugins.tools.data;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class JadxPluginMetadata implements Comparable<JadxPluginMetadata> {
|
||||
private String pluginId;
|
||||
private String name;
|
||||
@@ -11,8 +13,15 @@ public class JadxPluginMetadata implements Comparable<JadxPluginMetadata> {
|
||||
private @Nullable String requiredJadxVersion;
|
||||
|
||||
private @Nullable String version;
|
||||
|
||||
private String locationId;
|
||||
private String jar;
|
||||
|
||||
/**
|
||||
* Absolute path to '.jar' file or unpacked zip directory
|
||||
*/
|
||||
@SerializedName(value = "path", alternate = { "jar" })
|
||||
private String path;
|
||||
|
||||
private boolean disabled;
|
||||
|
||||
public String getPluginId() {
|
||||
@@ -71,12 +80,22 @@ public class JadxPluginMetadata implements Comparable<JadxPluginMetadata> {
|
||||
this.locationId = locationId;
|
||||
}
|
||||
|
||||
public String getJar() {
|
||||
return jar;
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public String getJar() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setJar(String jar) {
|
||||
this.jar = jar;
|
||||
this.path = jar;
|
||||
}
|
||||
|
||||
public boolean isDisabled() {
|
||||
@@ -115,7 +134,7 @@ public class JadxPluginMetadata implements Comparable<JadxPluginMetadata> {
|
||||
+ ", name=" + name
|
||||
+ ", version=" + (version != null ? version : "?")
|
||||
+ ", locationId=" + locationId
|
||||
+ ", jar=" + jar
|
||||
+ ", path=" + path
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
|
||||
+10
-5
@@ -20,18 +20,23 @@ public class LocalFileResolver implements IJadxPluginResolver {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isValidFileLocation(String locationId) {
|
||||
return locationId.startsWith("file:")
|
||||
&& (locationId.endsWith(".jar") || locationId.endsWith(".zip"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<JadxPluginMetadata> resolve(String locationId) {
|
||||
if (!locationId.startsWith("file:") || !locationId.endsWith(".jar")) {
|
||||
if (!isValidFileLocation(locationId)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
File jarFile = new File(removePrefix(locationId, "file:"));
|
||||
if (!jarFile.isFile()) {
|
||||
throw new RuntimeException("File not found: " + jarFile.getAbsolutePath());
|
||||
File pluginFile = new File(removePrefix(locationId, "file:"));
|
||||
if (!pluginFile.isFile()) {
|
||||
throw new RuntimeException("File not found: " + pluginFile.getAbsolutePath());
|
||||
}
|
||||
JadxPluginMetadata metadata = new JadxPluginMetadata();
|
||||
metadata.setLocationId(locationId);
|
||||
metadata.setJar(jarFile.getAbsolutePath());
|
||||
metadata.setPath(pluginFile.getAbsolutePath());
|
||||
return Optional.of(metadata);
|
||||
}
|
||||
|
||||
|
||||
+18
-8
@@ -5,6 +5,8 @@ import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.utils.ListUtils;
|
||||
import jadx.plugins.tools.data.JadxPluginMetadata;
|
||||
import jadx.plugins.tools.resolvers.IJadxPluginResolver;
|
||||
@@ -58,7 +60,7 @@ public class GithubReleaseResolver implements IJadxPluginResolver {
|
||||
JadxPluginMetadata metadata = new JadxPluginMetadata();
|
||||
metadata.setVersion(releaseVersion);
|
||||
metadata.setLocationId(buildLocationIdWithoutVersion(info)); // exclude version for later updates
|
||||
metadata.setJar(asset.getDownloadUrl());
|
||||
metadata.setPath(asset.getDownloadUrl());
|
||||
return metadata;
|
||||
}
|
||||
|
||||
@@ -89,20 +91,28 @@ public class GithubReleaseResolver implements IJadxPluginResolver {
|
||||
}
|
||||
|
||||
private static Asset searchPluginAsset(List<Asset> assets, String artifactPrefix, String releaseVersion) {
|
||||
String artifactName = artifactPrefix + '-' + releaseVersion + ".jar";
|
||||
Asset assetJar = searchAssetWithExt(assets, artifactPrefix, releaseVersion, ".jar");
|
||||
if (assetJar != null) {
|
||||
return assetJar;
|
||||
}
|
||||
Asset assetZip = searchAssetWithExt(assets, artifactPrefix, releaseVersion, ".zip");
|
||||
if (assetZip != null) {
|
||||
return assetZip;
|
||||
}
|
||||
throw new RuntimeException("Release artifact with prefix '" + artifactPrefix + "' not found");
|
||||
}
|
||||
|
||||
private static @Nullable Asset searchAssetWithExt(List<Asset> assets, String artifactPrefix, String releaseVersion, String ext) {
|
||||
String artifactName = artifactPrefix + '-' + releaseVersion + ext;
|
||||
Asset exactAsset = ListUtils.filterOnlyOne(assets, a -> a.getName().equals(artifactName));
|
||||
if (exactAsset != null) {
|
||||
return exactAsset;
|
||||
}
|
||||
// search without version filter
|
||||
Asset foundAsset = ListUtils.filterOnlyOne(assets, a -> {
|
||||
return ListUtils.filterOnlyOne(assets, a -> {
|
||||
String assetFileName = a.getName();
|
||||
return assetFileName.startsWith(artifactPrefix) && assetFileName.endsWith(".jar");
|
||||
return assetFileName.startsWith(artifactPrefix) && assetFileName.endsWith(ext);
|
||||
});
|
||||
if (foundAsset != null) {
|
||||
return foundAsset;
|
||||
}
|
||||
throw new RuntimeException("Release artifact with prefix '" + artifactPrefix + "' not found");
|
||||
}
|
||||
|
||||
private static String buildLocationIdWithoutVersion(LocationInfo info) {
|
||||
|
||||
Reference in New Issue
Block a user