From 347d6e2c2edae9cb935a33049f65f4d496bd88f5 Mon Sep 17 00:00:00 2001 From: Skylot Date: Wed, 7 Jun 2023 22:09:06 +0100 Subject: [PATCH] refactor: improve github plugin resolver --- .../settings/ui/plugins/PluginsSettings.java | 8 +- .../github/GithubReleaseResolver.java | 86 +++++++++++-------- .../tools/resolvers/github/LocationInfo.java | 33 +++++++ 3 files changed, 87 insertions(+), 40 deletions(-) create mode 100644 jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/LocationInfo.java diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ui/plugins/PluginsSettings.java b/jadx-gui/src/main/java/jadx/gui/settings/ui/plugins/PluginsSettings.java index d5f8c3636..b259e3959 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/ui/plugins/PluginsSettings.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/ui/plugins/PluginsSettings.java @@ -69,11 +69,11 @@ public class PluginsSettings { mainWindow.getBackgroundExecutor().execute(NLS.str("preferences.plugins.task.uninstalling"), () -> { boolean success = JadxPluginsTools.getInstance().uninstall(pluginId); if (success) { - LOG.debug("Uninstall complete"); + LOG.info("Uninstall complete"); mainWindow.events().send(ReloadSettingsWindow.INSTANCE); UiUtils.uiRun(mainWindow::reopen); } else { - LOG.debug("Uninstall failed"); + LOG.warn("Uninstall failed"); } }); } @@ -82,11 +82,11 @@ public class PluginsSettings { mainWindow.getBackgroundExecutor().execute(NLS.str("preferences.plugins.task.updating"), () -> { List updates = JadxPluginsTools.getInstance().updateAll(); if (!updates.isEmpty()) { - LOG.debug("Updates: {}\n ", Utils.listToString(updates, "\n ")); + LOG.info("Updates: {}\n ", Utils.listToString(updates, "\n ")); mainWindow.events().send(ReloadSettingsWindow.INSTANCE); UiUtils.uiRun(mainWindow::reopen); } else { - LOG.debug("No updates found"); + LOG.info("No updates found"); } }); } diff --git a/jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/GithubReleaseResolver.java b/jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/GithubReleaseResolver.java index 8769d9247..eb499a7ef 100644 --- a/jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/GithubReleaseResolver.java +++ b/jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/GithubReleaseResolver.java @@ -5,19 +5,17 @@ import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.Type; import java.net.HttpURLConnection; -import java.net.URL; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import jadx.core.utils.ListUtils; import jadx.plugins.tools.data.JadxPluginMetadata; import jadx.plugins.tools.resolvers.IJadxPluginResolver; import jadx.plugins.tools.resolvers.github.data.Asset; @@ -36,12 +34,30 @@ public class GithubReleaseResolver implements IJadxPluginResolver { @Override public Optional resolve(String locationId) { - if (!locationId.startsWith("github:")) { + LocationInfo info = parseLocation(locationId); + if (info == null) { return Optional.empty(); } + Release release = fetchRelease(info); + List assets = release.getAssets(); + String releaseVersion = removePrefix(release.getName(), "v"); + Asset asset = searchPluginAsset(assets, info.getArtifactPrefix(), releaseVersion); + + JadxPluginMetadata metadata = new JadxPluginMetadata(); + metadata.setResolverId(id()); + metadata.setVersion(releaseVersion); + metadata.setLocationId(buildLocationIdWithoutVersion(info)); // exclude version for later updates + metadata.setJar(asset.getDownloadUrl()); + return Optional.of(metadata); + } + + private static LocationInfo parseLocation(String locationId) { + if (!locationId.startsWith("github:")) { + return null; + } String[] parts = locationId.split(":"); if (parts.length < 3) { - return Optional.empty(); + return null; } String owner = parts[1]; String project = parts[2]; @@ -58,39 +74,37 @@ public class GithubReleaseResolver implements IJadxPluginResolver { artifactPrefix = part; } } - Release release = getRelease(owner, project, version); - String releaseVersion = removePrefix(release.getName(), "v"); + return new LocationInfo(owner, project, artifactPrefix, version); + } + + private static Asset searchPluginAsset(List assets, String artifactPrefix, String releaseVersion) { String artifactName = artifactPrefix + '-' + releaseVersion + ".jar"; - Asset asset = release.getAssets().stream() - .filter(a -> a.getName().equals(artifactName)) - .findFirst() - .orElse(searchIgnoringVersion(release, artifactPrefix)); - - JadxPluginMetadata metadata = new JadxPluginMetadata(); - metadata.setResolverId(id()); - metadata.setVersion(releaseVersion); - metadata.setLocationId(buildLocationId(owner, project, artifactPrefix)); // exclude version for later updates - metadata.setJar(asset.getDownloadUrl()); - return Optional.of(metadata); - } - - private @NotNull Asset searchIgnoringVersion(Release release, String artifactPrefix) { - return release.getAssets().stream() - .filter(a -> a.getName().startsWith(artifactPrefix) && a.getName().startsWith(".jar")) - .findFirst() - .orElseThrow(() -> new RuntimeException("Release artifact with prefix '" + artifactPrefix + "' not found")); - } - - @NotNull - private static String buildLocationId(String owner, String project, String artifactPrefix) { - if (project.equals(artifactPrefix)) { - return "github:" + owner + ':' + project; + Asset exactAsset = ListUtils.filterOnlyOne(assets, a -> a.getName().equals(artifactName)); + if (exactAsset != null) { + return exactAsset; } - return "github:" + owner + ':' + project + ':' + artifactPrefix; + // search without version + Asset foundAsset = ListUtils.filterOnlyOne(assets, a -> { + String assetFileName = a.getName(); + return assetFileName.startsWith(artifactPrefix) && assetFileName.endsWith(".jar"); + }); + if (foundAsset != null) { + return foundAsset; + } + throw new RuntimeException("Release artifact with prefix '" + artifactPrefix + "' not found"); } - private static Release getRelease(String owner, String project, @Nullable String version) { - String projectUrl = GITHUB_API_URL + "repos/" + owner + "/" + project; + private static String buildLocationIdWithoutVersion(LocationInfo info) { + String baseLocation = "github:" + info.getOwner() + ':' + info.getProject(); + if (info.getProject().equals(info.getArtifactPrefix())) { + return baseLocation; + } + return baseLocation + ':' + info.getArtifactPrefix(); + } + + private static Release fetchRelease(LocationInfo info) { + String projectUrl = GITHUB_API_URL + "repos/" + info.getOwner() + "/" + info.getProject(); + String version = info.getVersion(); if (version == null) { // get latest version return get(projectUrl + "/releases/latest", RELEASE_TYPE); @@ -107,7 +121,7 @@ public class GithubReleaseResolver implements IJadxPluginResolver { private static T get(String url, Type type) { HttpURLConnection con; try { - con = (HttpURLConnection) new URL(url).openConnection(); + con = (HttpURLConnection) URI.create(url).toURL().openConnection(); con.setRequestMethod("GET"); int code = con.getResponseCode(); if (code != 200) { diff --git a/jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/LocationInfo.java b/jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/LocationInfo.java new file mode 100644 index 000000000..207c879cf --- /dev/null +++ b/jadx-plugins-tools/src/main/java/jadx/plugins/tools/resolvers/github/LocationInfo.java @@ -0,0 +1,33 @@ +package jadx.plugins.tools.resolvers.github; + +import org.jetbrains.annotations.Nullable; + +class LocationInfo { + private final String owner; + private final String project; + private final String artifactPrefix; + private final @Nullable String version; + + public LocationInfo(String owner, String project, String artifactPrefix, @Nullable String version) { + this.owner = owner; + this.project = project; + this.artifactPrefix = artifactPrefix; + this.version = version; + } + + public String getOwner() { + return owner; + } + + public String getProject() { + return project; + } + + public String getArtifactPrefix() { + return artifactPrefix; + } + + public @Nullable String getVersion() { + return version; + } +}