From bb49ba8ad214b33d5bb815532656ed14cfba11d4 Mon Sep 17 00:00:00 2001 From: Luca Stocchi Date: Fri, 25 Feb 2022 15:36:17 +0100 Subject: [PATCH 1/4] feat: add silentMode to DownloadHelper (#121) Signed-off-by: Luca Stocchi --- .../intellij/common/utils/DownloadHelper.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java index ddd303d..7564953 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java @@ -115,10 +115,11 @@ public static DownloadHelper getInstance() { * * @param toolName the name of the tool to download * @param url the URL to the tool description file + * @param silentMode to define if user should confirm download. If true the download will start automatically. * @return the command path * @throws IOException if the tool was not found in the config file */ - public String downloadIfRequired(String toolName, URL url) throws IOException { + public String downloadIfRequired(String toolName, URL url, boolean silentMode) throws IOException { ToolsConfig config = ConfigHelper.loadToolsConfig(url); ToolsConfig.Tool tool = config.getTools().get(toolName); if (tool == null) { @@ -132,18 +133,18 @@ public String downloadIfRequired(String toolName, URL url) throws IOException { if (!Files.exists(path)) { final Path dlFilePath = path.resolveSibling(platform.getDlFileName()); final String cmd = path.toString(); - if (isDownloadAllowed(toolName, version, tool.getVersion())) { + if (silentMode || isDownloadAllowed(toolName, version, tool.getVersion())) { command = ProgressManager.getInstance().run(new Task.WithResult(null, "Downloading " + toolName, true) { @Override public String compute(@NotNull ProgressIndicator progressIndicator) throws IOException { return HttpRequests.request(platform.getUrl().toString()).useProxy(true).connect(request -> { - downloadFile(request.getInputStream(), dlFilePath, progressIndicator, request.getConnection().getContentLength()); - if (progressIndicator.isCanceled()) { - throw new IOException("Cancelled"); - } else { - uncompress(dlFilePath, path); - return cmd; - } + downloadFile(request.getInputStream(), dlFilePath, progressIndicator, request.getConnection().getContentLength()); + if (progressIndicator.isCanceled()) { + throw new IOException("Cancelled"); + } else { + uncompress(dlFilePath, path); + return cmd; + } }); } }); @@ -155,11 +156,15 @@ public String compute(@NotNull ProgressIndicator progressIndicator) throws IOExc return command; } - public CompletableFuture downloadIfRequiredAsync(String toolName, URL url) { + public String downloadIfRequired(String toolName, URL url) throws IOException { + return downloadIfRequired(toolName, url, false); + } + + public CompletableFuture downloadIfRequiredAsync(String toolName, URL url, boolean silentMode) { CompletableFuture result = new CompletableFuture<>(); ApplicationManager.getApplication().invokeLater(() -> { try { - result.complete(downloadIfRequired(toolName, url)); + result.complete(downloadIfRequired(toolName, url, silentMode)); } catch (IOException e) { result.completeExceptionally(e); } @@ -167,6 +172,10 @@ public CompletableFuture downloadIfRequiredAsync(String toolName, URL ur return result; } + public CompletableFuture downloadIfRequiredAsync(String toolName, URL url) { + return downloadIfRequiredAsync(toolName, url, false); + } + private boolean isDownloadAllowed(String tool, String currentVersion, String requiredVersion) { return Messages.showYesNoCancelDialog(StringUtils.isEmpty(currentVersion) ? tool + " not found , do you want to download " + tool + " " + requiredVersion + " ?" : tool + " " + currentVersion + " found, required version is " + requiredVersion + ", do you want to download " + tool + " ?", tool + " tool required", Messages.getQuestionIcon()) == Messages.YES; } From b5e221a9c77117d3c6c7747abccfdc840729491a Mon Sep 17 00:00:00 2001 From: Luca Stocchi Date: Mon, 28 Feb 2022 12:57:20 +0100 Subject: [PATCH 2/4] change download to background task Signed-off-by: Luca Stocchi --- .../intellij/common/utils/DownloadHelper.java | 48 +++++++++---------- .../intellij/common/utils/ToolsConfig.java | 9 ++++ src/test/resources/tkn-test-gz.json | 1 + src/test/resources/tkn-test-tar.gz.json | 1 + src/test/resources/tkn-test.json | 1 + 5 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java index 7564953..a0c6f41 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.UnaryOperator; import java.util.regex.Pattern; @@ -91,6 +92,7 @@ public static DownloadHelper getInstance() { * "versionExtractRegExp": "", //the regular expression to extract the version string from the version command * "versionMatchRegExpr": "", //the regular expression use to match the extracted version to decide if download if required * "baseDir": "" //the basedir to install to, a sub folder named after version will be created, can use $HOME + * "silentMode": true, //if the download needs to be started automatically without user input * "platforms": { * "win": { * "url": "https://tool.com/tool/v1.0.0/odo-windows-amd64.exe.tar.gz", @@ -115,56 +117,54 @@ public static DownloadHelper getInstance() { * * @param toolName the name of the tool to download * @param url the URL to the tool description file - * @param silentMode to define if user should confirm download. If true the download will start automatically. * @return the command path * @throws IOException if the tool was not found in the config file */ - public String downloadIfRequired(String toolName, URL url, boolean silentMode) throws IOException { + public String downloadIfRequired(String toolName, URL url) throws IOException { ToolsConfig config = ConfigHelper.loadToolsConfig(url); ToolsConfig.Tool tool = config.getTools().get(toolName); if (tool == null) { throw new IOException("Tool " + toolName + " not found in config file " + url); } ToolsConfig.Platform platform = tool.getPlatforms().get(Platform.os().id()); - String command = platform.getCmdFileName(); + AtomicReference command = new AtomicReference<>(platform.getCmdFileName()); String version = getVersionFromPath(tool, platform); if (!areCompatible(version, tool.getVersionMatchRegExpr())) { - Path path = Paths.get(tool.getBaseDir().replace("$HOME", CommonConstants.HOME_FOLDER), "cache", tool.getVersion(), command); + Path path = Paths.get(tool.getBaseDir().replace("$HOME", CommonConstants.HOME_FOLDER), "cache", tool.getVersion(), command.get()); if (!Files.exists(path)) { final Path dlFilePath = path.resolveSibling(platform.getDlFileName()); final String cmd = path.toString(); - if (silentMode || isDownloadAllowed(toolName, version, tool.getVersion())) { - command = ProgressManager.getInstance().run(new Task.WithResult(null, "Downloading " + toolName, true) { + if (tool.isSilentMode() || isDownloadAllowed(toolName, version, tool.getVersion())) { + ProgressManager.getInstance().run(new Task.Backgroundable(null, "Downloading " + toolName, false) { @Override - public String compute(@NotNull ProgressIndicator progressIndicator) throws IOException { - return HttpRequests.request(platform.getUrl().toString()).useProxy(true).connect(request -> { - downloadFile(request.getInputStream(), dlFilePath, progressIndicator, request.getConnection().getContentLength()); - if (progressIndicator.isCanceled()) { - throw new IOException("Cancelled"); - } else { + public void run(@NotNull ProgressIndicator progressIndicator) { + String result = ""; + try { + result = HttpRequests.request(platform.getUrl().toString()).useProxy(true).connect(request -> { + downloadFile(request.getInputStream(), dlFilePath, progressIndicator, request.getConnection().getContentLength()); uncompress(dlFilePath, path); return cmd; - } - }); + }); + } catch (IOException ignored) { } + command.set(result); } }); } } else { - command = path.toString(); + command.set(path.toString()); } } - return command; - } - - public String downloadIfRequired(String toolName, URL url) throws IOException { - return downloadIfRequired(toolName, url, false); + if (command.get().isEmpty()) { + throw new IOException("Error while setting tool " + toolName + "."); + } + return command.get(); } - public CompletableFuture downloadIfRequiredAsync(String toolName, URL url, boolean silentMode) { + public CompletableFuture downloadIfRequiredAsync(String toolName, URL url) { CompletableFuture result = new CompletableFuture<>(); ApplicationManager.getApplication().invokeLater(() -> { try { - result.complete(downloadIfRequired(toolName, url, silentMode)); + result.complete(downloadIfRequired(toolName, url)); } catch (IOException e) { result.completeExceptionally(e); } @@ -172,10 +172,6 @@ public CompletableFuture downloadIfRequiredAsync(String toolName, URL ur return result; } - public CompletableFuture downloadIfRequiredAsync(String toolName, URL url) { - return downloadIfRequiredAsync(toolName, url, false); - } - private boolean isDownloadAllowed(String tool, String currentVersion, String requiredVersion) { return Messages.showYesNoCancelDialog(StringUtils.isEmpty(currentVersion) ? tool + " not found , do you want to download " + tool + " " + requiredVersion + " ?" : tool + " " + currentVersion + " found, required version is " + requiredVersion + ", do you want to download " + tool + " ?", tool + " tool required", Messages.getQuestionIcon()) == Messages.YES; } diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/ToolsConfig.java b/src/main/java/com/redhat/devtools/intellij/common/utils/ToolsConfig.java index cbd1f6b..3dc3c7c 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/ToolsConfig.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/ToolsConfig.java @@ -26,6 +26,7 @@ public static class Tool { private String versionExtractRegExp; private String versionMatchRegExpr; private String baseDir; + private boolean silentMode; public Map getPlatforms() { return platforms; @@ -74,6 +75,14 @@ public String getBaseDir() { public void setBaseDir(String baseDir) { this.baseDir = baseDir; } + + public boolean isSilentMode() { + return silentMode; + } + + public void setSilentMode(boolean silentMode) { + this.silentMode = silentMode; + } } public static class Platform { diff --git a/src/test/resources/tkn-test-gz.json b/src/test/resources/tkn-test-gz.json index b7cf3e7..e7586b3 100644 --- a/src/test/resources/tkn-test-gz.json +++ b/src/test/resources/tkn-test-gz.json @@ -6,6 +6,7 @@ "versionExtractRegExp": "Client version: (\\d+[\\.\\d+]*)\\s.*", "versionMatchRegExpr": "0\\..*", "baseDir": ".", + "silentMode": true, "platforms": { "win": { "url": "file:src/test/resources/tkn.gz", diff --git a/src/test/resources/tkn-test-tar.gz.json b/src/test/resources/tkn-test-tar.gz.json index f5036d0..b38adf2 100644 --- a/src/test/resources/tkn-test-tar.gz.json +++ b/src/test/resources/tkn-test-tar.gz.json @@ -6,6 +6,7 @@ "versionExtractRegExp": "Client version: (\\d+[\\.\\d+]*)\\s.*", "versionMatchRegExpr": "0\\..*", "baseDir": ".", + "silentMode": true, "platforms": { "win": { "url": "file:src/test/resources/tkn.tar.gz", diff --git a/src/test/resources/tkn-test.json b/src/test/resources/tkn-test.json index 9eb8cb8..1f8bafe 100644 --- a/src/test/resources/tkn-test.json +++ b/src/test/resources/tkn-test.json @@ -6,6 +6,7 @@ "versionExtractRegExp": "Client version: (\\d+[\\.\\d+]*)\\s.*", "versionMatchRegExpr": "0\\..*", "baseDir": "$HOME/.tekton", + "silentMode": true, "platforms": { "win": { "url": "https://github.com/tektoncd/cli/releases/download/v0.5.0/tkn_0.5.0_Windows_x86_64.zip", From 5094b06b9b44bc78a7212134f189f53d26852388 Mon Sep 17 00:00:00 2001 From: Luca Stocchi Date: Wed, 2 Mar 2022 12:15:31 +0100 Subject: [PATCH 3/4] run download in background task Signed-off-by: Luca Stocchi --- .../intellij/common/utils/DownloadHelper.java | 89 ++++++++++++------- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java index a0c6f41..d5af17f 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java @@ -11,6 +11,7 @@ package com.redhat.devtools.intellij.common.utils; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -42,7 +43,10 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.regex.Pattern; @@ -120,55 +124,80 @@ public static DownloadHelper getInstance() { * @return the command path * @throws IOException if the tool was not found in the config file */ - public String downloadIfRequired(String toolName, URL url) throws IOException { + private CompletableFuture downloadIfRequiredAsyncInner(String toolName, URL url) throws IOException { + CompletableFuture result = new CompletableFuture<>(); ToolsConfig config = ConfigHelper.loadToolsConfig(url); ToolsConfig.Tool tool = config.getTools().get(toolName); if (tool == null) { throw new IOException("Tool " + toolName + " not found in config file " + url); } ToolsConfig.Platform platform = tool.getPlatforms().get(Platform.os().id()); - AtomicReference command = new AtomicReference<>(platform.getCmdFileName()); + String command = platform.getCmdFileName(); String version = getVersionFromPath(tool, platform); if (!areCompatible(version, tool.getVersionMatchRegExpr())) { - Path path = Paths.get(tool.getBaseDir().replace("$HOME", CommonConstants.HOME_FOLDER), "cache", tool.getVersion(), command.get()); + Path path = Paths.get(tool.getBaseDir().replace("$HOME", CommonConstants.HOME_FOLDER), "cache", tool.getVersion(), command); + final String cmd = path.toString(); if (!Files.exists(path)) { - final Path dlFilePath = path.resolveSibling(platform.getDlFileName()); - final String cmd = path.toString(); if (tool.isSilentMode() || isDownloadAllowed(toolName, version, tool.getVersion())) { - ProgressManager.getInstance().run(new Task.Backgroundable(null, "Downloading " + toolName, false) { - @Override - public void run(@NotNull ProgressIndicator progressIndicator) { - String result = ""; - try { - result = HttpRequests.request(platform.getUrl().toString()).useProxy(true).connect(request -> { - downloadFile(request.getInputStream(), dlFilePath, progressIndicator, request.getConnection().getContentLength()); - uncompress(dlFilePath, path); - return cmd; - }); - } catch (IOException ignored) { } - command.set(result); - } - }); + if (ApplicationManager.getApplication().isUnitTestMode()) { + downloadInBackground(toolName, platform, path, cmd, result); + } else { + ApplicationManager.getApplication().invokeLater(() -> downloadInBackground(toolName, platform, path, cmd, result)); + } + } else { + result.complete(command); } } else { - command.set(path.toString()); + result.complete(cmd); } + } else { + result.complete(command); } - if (command.get().isEmpty()) { - throw new IOException("Error while setting tool " + toolName + "."); + + return result; + } + + private void downloadInBackground(String toolName, ToolsConfig.Platform platform, Path path, String cmd, CompletableFuture result) { + final Path dlFilePath = path.resolveSibling(platform.getDlFileName()); + ProgressManager.getInstance().run(new Task.Backgroundable(null, "Downloading " + toolName, false) { + @Override + public void run(@NotNull ProgressIndicator progressIndicator) { + try { + HttpRequests.request(platform.getUrl().toString()).useProxy(true).connect(request -> { + downloadFile(request.getInputStream(), dlFilePath, progressIndicator, request.getConnection().getContentLength()); + uncompress(dlFilePath, path); + return cmd; + }); + } catch (IOException ignored) { + result.completeExceptionally(new IOException("Error while setting tool " + toolName + ".")); + } + } + + @Override + public void onFinished() { + if (!result.isCompletedExceptionally()) { + result.complete(cmd); + } + } + }); + } + + public String downloadIfRequired(String toolName, URL url) throws IOException { + CompletableFuture future = downloadIfRequiredAsyncInner(toolName, url); + try { + return future.get(); + } catch (InterruptedException | ExecutionException e) { + throw new IOException(e); } - return command.get(); } public CompletableFuture downloadIfRequiredAsync(String toolName, URL url) { CompletableFuture result = new CompletableFuture<>(); - ApplicationManager.getApplication().invokeLater(() -> { - try { - result.complete(downloadIfRequired(toolName, url)); - } catch (IOException e) { - result.completeExceptionally(e); - } - }); + try { + return downloadIfRequiredAsyncInner(toolName, url); + } catch (IOException e) { + result.completeExceptionally(e); + } return result; } From 6333c8faf292b95f099ccb79e27ca80eaffea26b Mon Sep 17 00:00:00 2001 From: Luca Stocchi Date: Wed, 2 Mar 2022 15:06:38 +0100 Subject: [PATCH 4/4] fix running dialog in dispatch thread Signed-off-by: Luca Stocchi --- .../intellij/common/utils/DownloadHelper.java | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java index d5af17f..4c1baf2 100644 --- a/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java +++ b/src/main/java/com/redhat/devtools/intellij/common/utils/DownloadHelper.java @@ -16,6 +16,7 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Computable; import com.intellij.util.io.HttpRequests; import com.redhat.devtools.intellij.common.CommonConstants; import com.twelvemonkeys.lang.Platform; @@ -138,15 +139,7 @@ private CompletableFuture downloadIfRequiredAsyncInner(String toolName, Path path = Paths.get(tool.getBaseDir().replace("$HOME", CommonConstants.HOME_FOLDER), "cache", tool.getVersion(), command); final String cmd = path.toString(); if (!Files.exists(path)) { - if (tool.isSilentMode() || isDownloadAllowed(toolName, version, tool.getVersion())) { - if (ApplicationManager.getApplication().isUnitTestMode()) { - downloadInBackground(toolName, platform, path, cmd, result); - } else { - ApplicationManager.getApplication().invokeLater(() -> downloadInBackground(toolName, platform, path, cmd, result)); - } - } else { - result.complete(command); - } + downloadInBackground(toolName, platform, path, cmd, tool, version, result); } else { result.complete(cmd); } @@ -157,7 +150,21 @@ private CompletableFuture downloadIfRequiredAsyncInner(String toolName, return result; } - private void downloadInBackground(String toolName, ToolsConfig.Platform platform, Path path, String cmd, CompletableFuture result) { + private void downloadInBackground(String toolName, ToolsConfig.Platform platform, Path path, String cmd, ToolsConfig.Tool tool, String version, CompletableFuture result) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + downloadInBackgroundManager(toolName, platform, path, cmd, result); + } else { + ApplicationManager.getApplication().invokeLater(() -> { + if (tool.isSilentMode() || isDownloadAllowed(toolName, version, tool.getVersion())) { + downloadInBackgroundManager(toolName, platform, path, cmd, result); + } else { + result.complete(platform.getCmdFileName()); + } + }); + } + } + + private void downloadInBackgroundManager(String toolName, ToolsConfig.Platform platform, Path path, String cmd, CompletableFuture result) { final Path dlFilePath = path.resolveSibling(platform.getDlFileName()); ProgressManager.getInstance().run(new Task.Backgroundable(null, "Downloading " + toolName, false) { @Override @@ -202,7 +209,8 @@ public CompletableFuture downloadIfRequiredAsync(String toolName, URL ur } private boolean isDownloadAllowed(String tool, String currentVersion, String requiredVersion) { - return Messages.showYesNoCancelDialog(StringUtils.isEmpty(currentVersion) ? tool + " not found , do you want to download " + tool + " " + requiredVersion + " ?" : tool + " " + currentVersion + " found, required version is " + requiredVersion + ", do you want to download " + tool + " ?", tool + " tool required", Messages.getQuestionIcon()) == Messages.YES; + return UIHelper.executeInUI(() -> + Messages.showYesNoCancelDialog(StringUtils.isEmpty(currentVersion) ? tool + " not found , do you want to download " + tool + " " + requiredVersion + " ?" : tool + " " + currentVersion + " found, required version is " + requiredVersion + ", do you want to download " + tool + " ?", tool + " tool required", Messages.getQuestionIcon()) == Messages.YES); } private boolean areCompatible(String version, String versionMatchRegExpr) {