diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
index 5a987494f..d0185dcf9 100644
--- a/CHANGELOG.adoc
+++ b/CHANGELOG.adoc
@@ -4,9 +4,18 @@ This file documents all notable changes to https://github.com/devonfw/IDEasy[IDE
== 2024.12.001
+NOTE: ATTENTION: When installing this release as an update, you need to manually remove IDEasy entries from `.bashrc` and if present also `.zshrc`.
+Also you should delete all files from your `$IDE_ROOT/_ide` folder before extracting the new version to it.
+Then run the `setup` and all should work fine.
+
Release with new features and bugfixes:
+* https://github.com/devonfw/IDEasy/issues/774[#774]: HTTP proxy support not working properly
* https://github.com/devonfw/IDEasy/issues/589[#589]: Fix NLS Bundles for Linux and MacOS
+* https://github.com/devonfw/IDEasy/issues/778[#778]: Add icd command
+* https://github.com/devonfw/IDEasy/issues/779[#779]: Consider functions instead of alias
+* https://github.com/devonfw/IDEasy/issues/810[#810]: setup not adding IDEasy to current shell
+* https://github.com/devonfw/IDEasy/issues/782[#782]: Fix IDE_ROOT variable on Linux
* https://github.com/devonfw/IDEasy/issues/637[#637]: Added option to disable updates
* https://github.com/devonfw/IDEasy/issues/764[#764]: IDEasy not working properly in CMD
* https://github.com/devonfw/IDEasy/issues/81[#81]: Implement Toolcommandlet for Kubernetes
diff --git a/cli/pom.xml b/cli/pom.xml
index 34b3c44cf..5fc508d9a 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -68,13 +68,6 @@
1.5.3
-
-
- com.github.tomakehurst
- wiremock-jre8
- 2.35.1
- test
-
me.tongfei
progressbar
@@ -90,6 +83,21 @@
jansi
${jansi.version}
+
+
+
+ org.mockito
+ mockito-core
+ 5.10.0
+ test
+
+
+
+ com.github.tomakehurst
+ wiremock-jre8
+ 2.35.1
+ test
+
net.bytebuddy
@@ -102,11 +110,13 @@
org.xmlunit
xmlunit-core
2.10.0
+ test
org.xmlunit
xmlunit-assertj3
2.9.1
+ test
diff --git a/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java b/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java
index 06bf22e66..657147de1 100644
--- a/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java
+++ b/cli/src/main/java/com/devonfw/tools/ide/context/AbstractIdeContext.java
@@ -28,13 +28,15 @@
import com.devonfw.tools.ide.environment.AbstractEnvironmentVariables;
import com.devonfw.tools.ide.environment.EnvironmentVariables;
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
+import com.devonfw.tools.ide.environment.IdeSystem;
+import com.devonfw.tools.ide.environment.IdeSystemImpl;
import com.devonfw.tools.ide.io.FileAccess;
import com.devonfw.tools.ide.io.FileAccessImpl;
import com.devonfw.tools.ide.log.IdeLogLevel;
import com.devonfw.tools.ide.log.IdeLogger;
import com.devonfw.tools.ide.log.IdeSubLogger;
import com.devonfw.tools.ide.merge.DirectoryMerger;
-import com.devonfw.tools.ide.network.ProxyContext;
+import com.devonfw.tools.ide.network.NetworkProxy;
import com.devonfw.tools.ide.os.SystemInfo;
import com.devonfw.tools.ide.os.SystemInfoImpl;
import com.devonfw.tools.ide.os.WindowsPathSyntax;
@@ -124,6 +126,10 @@ public abstract class AbstractIdeContext implements IdeContext {
protected Boolean online;
+ protected IdeSystem system;
+
+ private NetworkProxy networkProxy;
+
/**
* The constructor.
*
@@ -202,8 +208,8 @@ private Path findIdeRoot(Path ideHomePath) {
return ideRootPath;
}
- private static Path getIdeRootPathFromEnv() {
- String root = System.getenv(IdeVariables.IDE_ROOT.getName());
+ private Path getIdeRootPathFromEnv() {
+ String root = getSystem().getEnv(IdeVariables.IDE_ROOT.getName());
if (root != null) {
Path rootPath = Path.of(root);
if (Files.isDirectory(rootPath)) {
@@ -242,7 +248,7 @@ public void setCwd(Path userDir, String workspace, Path ideHome) {
this.userHome = this.ideHome.resolve("home");
}
} else {
- this.userHome = Path.of(System.getProperty("user.home"));
+ this.userHome = Path.of(getSystem().getProperty("user.home"));
}
this.userHomeIde = this.userHome.resolve(".ide");
this.downloadPath = this.userHome.resolve("Downloads/ide");
@@ -261,8 +267,8 @@ private String getMessageIdeHomeNotFound() {
return "You are not inside an IDE installation: " + this.cwd;
}
- private static String getMessageIdeRootNotFound() {
- String root = System.getenv("IDE_ROOT");
+ private String getMessageIdeRootNotFound() {
+ String root = getSystem().getEnv("IDE_ROOT");
if (root == null) {
return "The environment variable IDE_ROOT is undefined. Please reinstall IDEasy or manually repair IDE_ROOT variable.";
} else {
@@ -349,6 +355,8 @@ public SystemInfo getSystemInfo() {
@Override
public FileAccess getFileAccess() {
+ // currently FileAccess contains download method and requires network proxy to be configured. Maybe download should be moved to its own interface/class
+ configureNetworkProxy();
return this.fileAccess;
}
@@ -547,6 +555,7 @@ public boolean isSkipUpdatesMode() {
public boolean isOnline() {
if (this.online == null) {
+ configureNetworkProxy();
// we currently assume we have only a CLI process that runs shortly
// therefore we run this check only once to save resources when this method is called many times
try {
@@ -564,6 +573,13 @@ public boolean isOnline() {
return this.online.booleanValue();
}
+ private void configureNetworkProxy() {
+ if (this.networkProxy == null) {
+ this.networkProxy = new NetworkProxy(this);
+ this.networkProxy.configure();
+ }
+ }
+
@Override
public Locale getLocale() {
@@ -602,12 +618,6 @@ public void setDefaultExecutionDirectory(Path defaultExecutionDirectory) {
}
}
- @Override
- public ProxyContext getProxyContext() {
-
- return new ProxyContext(this);
- }
-
@Override
public GitContext getGitContext() {
@@ -624,6 +634,15 @@ public ProcessContext newProcess() {
return processContext;
}
+ @Override
+ public IdeSystem getSystem() {
+
+ if (this.system == null) {
+ this.system = new IdeSystemImpl(this);
+ }
+ return this.system;
+ }
+
/**
* @return a new instance of {@link ProcessContext}.
* @see #newProcess()
diff --git a/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java b/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java
index 077398198..3ca74ea16 100644
--- a/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java
+++ b/cli/src/main/java/com/devonfw/tools/ide/context/IdeContext.java
@@ -10,10 +10,10 @@
import com.devonfw.tools.ide.common.SystemPath;
import com.devonfw.tools.ide.environment.EnvironmentVariables;
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
+import com.devonfw.tools.ide.environment.IdeSystem;
import com.devonfw.tools.ide.io.FileAccess;
import com.devonfw.tools.ide.io.IdeProgressBar;
import com.devonfw.tools.ide.merge.DirectoryMerger;
-import com.devonfw.tools.ide.network.ProxyContext;
import com.devonfw.tools.ide.os.SystemInfo;
import com.devonfw.tools.ide.os.WindowsPathSyntax;
import com.devonfw.tools.ide.process.ProcessContext;
@@ -416,7 +416,10 @@ default Path getSettingsTemplatePath() {
*/
Path getDefaultExecutionDirectory();
- ProxyContext getProxyContext();
+ /**
+ * @return the {@link IdeSystem} instance wrapping {@link System}.
+ */
+ IdeSystem getSystem();
/**
* @return the {@link GitContext} used to run several git commands.
diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesSystem.java b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesSystem.java
index d2bde2173..0ec6d8b0f 100644
--- a/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesSystem.java
+++ b/cli/src/main/java/com/devonfw/tools/ide/environment/EnvironmentVariablesSystem.java
@@ -25,7 +25,7 @@ public EnvironmentVariablesType getType() {
@Override
protected Map getVariables() {
- return System.getenv();
+ return this.context.getSystem().getEnv();
}
/**
diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/IdeSystem.java b/cli/src/main/java/com/devonfw/tools/ide/environment/IdeSystem.java
new file mode 100644
index 000000000..ba03bcddf
--- /dev/null
+++ b/cli/src/main/java/com/devonfw/tools/ide/environment/IdeSystem.java
@@ -0,0 +1,44 @@
+package com.devonfw.tools.ide.environment;
+
+import java.util.Map;
+
+/**
+ * Interface to abstract from {@link System}.
+ */
+public interface IdeSystem {
+
+ /**
+ * @param key the name of the requested system property.
+ * @return the {@link System#getProperty(String) value} of the requested system property.
+ * @see System#getProperty(String)
+ */
+ String getProperty(String key);
+
+ /**
+ * @param key the name of the requested system property.
+ * @param fallback the value to return as default in case the requested system property is undefined.
+ * @return the {@link System#getProperty(String, String) value} of the requested system property.
+ * @see System#getProperty(String, String)
+ */
+ String getProperty(String key, String fallback);
+
+ /**
+ * @param key the name of the system property to set.
+ * @param value the new value to {@link System#setProperty(String, String) set}.
+ * @see System#setProperty(String, String)
+ */
+ void setProperty(String key, String value);
+
+ /**
+ * @param key the name of the requested environment variable.
+ * @return the {@link System#getenv(String) value} of the requested environment variable.
+ * @see System#getenv(String)
+ */
+ String getEnv(String key);
+
+ /**
+ * @return the {@link System#getenv() environment variables}.
+ */
+ Map getEnv();
+
+}
diff --git a/cli/src/main/java/com/devonfw/tools/ide/environment/IdeSystemImpl.java b/cli/src/main/java/com/devonfw/tools/ide/environment/IdeSystemImpl.java
new file mode 100644
index 000000000..880e11222
--- /dev/null
+++ b/cli/src/main/java/com/devonfw/tools/ide/environment/IdeSystemImpl.java
@@ -0,0 +1,80 @@
+package com.devonfw.tools.ide.environment;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+
+import com.devonfw.tools.ide.log.IdeLogger;
+
+/**
+ * Implementation of {@link IdeSystem}.
+ */
+public class IdeSystemImpl implements IdeSystem {
+
+ private final IdeLogger logger;
+
+ final Properties systemProperties;
+
+ final Map environmentVariables;
+
+ /**
+ * @param logger the {@link IdeLogger}.
+ */
+ public IdeSystemImpl(IdeLogger logger) {
+
+ this(logger, System.getProperties(), System.getenv());
+ }
+
+ /**
+ * @param logger the {@link IdeLogger}.
+ * @param systemProperties the {@link System#getProperties() system properties}.
+ * @param environmentVariables the {@link System#getenv() environment variables}.
+ */
+ protected IdeSystemImpl(IdeLogger logger, Properties systemProperties, Map environmentVariables) {
+
+ super();
+ this.logger = logger;
+ this.systemProperties = systemProperties;
+ this.environmentVariables = environmentVariables;
+ }
+
+ @Override
+ public String getProperty(String key) {
+
+ return this.systemProperties.getProperty(key);
+ }
+
+ @Override
+ public String getProperty(String key, String fallback) {
+
+ return this.systemProperties.getProperty(key, fallback);
+ }
+
+ @Override
+ public void setProperty(String key, String value) {
+
+ String old = getProperty(key);
+ if (Objects.equals(old, value)) {
+ this.logger.trace("System property was already set to {}={}", key, value);
+ } else {
+ this.systemProperties.put(key, value);
+ if (old == null) {
+ this.logger.trace("System property was set to {}={}", key, value);
+ } else {
+ this.logger.trace("System property was changed to {}={} from {}", key, value, old);
+ }
+ }
+ }
+
+ @Override
+ public String getEnv(String key) {
+
+ return this.environmentVariables.get(key);
+ }
+
+ @Override
+ public Map getEnv() {
+
+ return this.environmentVariables;
+ }
+}
diff --git a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java
index 9860df712..2ed74428e 100644
--- a/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java
+++ b/cli/src/main/java/com/devonfw/tools/ide/io/FileAccessImpl.java
@@ -6,9 +6,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Redirect;
@@ -82,12 +79,6 @@ public FileAccessImpl(IdeContext context) {
private HttpClient createHttpClient(String url) {
HttpClient.Builder builder = HttpClient.newBuilder().followRedirects(Redirect.ALWAYS);
- Proxy proxy = this.context.getProxyContext().getProxy(url);
- if (proxy != Proxy.NO_PROXY) {
- this.context.info("Downloading through proxy: " + proxy);
- InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address();
- builder.proxy(ProxySelector.of(proxyAddress));
- }
return builder.build();
}
@@ -105,7 +96,6 @@ public void download(String url, Path target) {
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).GET().build();
HttpClient client = createHttpClient(url);
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
-
if (response.statusCode() == 200) {
downloadFileWithProgressBar(url, target, response);
}
diff --git a/cli/src/main/java/com/devonfw/tools/ide/network/NetworkProxy.java b/cli/src/main/java/com/devonfw/tools/ide/network/NetworkProxy.java
new file mode 100644
index 000000000..80d78ada4
--- /dev/null
+++ b/cli/src/main/java/com/devonfw/tools/ide/network/NetworkProxy.java
@@ -0,0 +1,126 @@
+package com.devonfw.tools.ide.network;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Locale;
+
+import com.devonfw.tools.ide.context.IdeContext;
+import com.devonfw.tools.ide.environment.IdeSystem;
+import com.devonfw.tools.ide.log.IdeLogLevel;
+
+/**
+ * Simple class to {@link #configure()} network proxy.
+ */
+public class NetworkProxy {
+
+ private static final String PROXY_DOCUMENTATION_PAGE = "https://github.com/devonfw/IDEasy/blob/main/documentation/proxy-support.adoc";
+
+ private final IdeContext context;
+
+ private String nonProxyHosts;
+
+ private String allProxy;
+
+ /**
+ * @param context the {@link IdeContext}.
+ */
+ public NetworkProxy(IdeContext context) {
+
+ super();
+ this.context = context;
+ }
+
+ /**
+ * Perform the actual {@link NetworkProxy} configuration.
+ */
+ public void configure() {
+
+ setupNetworkProxy("http");
+ setupNetworkProxy("https");
+ }
+
+ private void setupNetworkProxy(String protocol) {
+
+ String systemPropertyProxyHost = protocol + ".proxyHost";
+ String configuredValue = System.getProperty(systemPropertyProxyHost);
+ if (configuredValue != null) {
+ this.context.trace("Proxy already configured via system property {}={}", systemPropertyProxyHost, configuredValue);
+ return;
+ }
+ String proxyUrlString = getProxyUrlFromEnvironmentVariable(protocol);
+ if (proxyUrlString == null) {
+ this.context.trace("No {} proxy configured.", protocol);
+ return;
+ }
+ try {
+ URL proxyUrl = new URL(proxyUrlString);
+ IdeSystem system = this.context.getSystem();
+ system.setProperty(systemPropertyProxyHost, proxyUrl.getHost());
+ int port = proxyUrl.getPort();
+ if (port == -1) {
+ String urlProtocol = proxyUrl.getProtocol().toLowerCase(Locale.ROOT);
+ if ("http".equals(urlProtocol)) {
+ port = 80;
+ } else if ("https".equals(urlProtocol)) {
+ port = 443;
+ } else if ("ftp".equals(urlProtocol)) {
+ port = 21;
+ }
+ }
+ system.setProperty(protocol + ".proxyPort", Integer.toString(port));
+ if (this.nonProxyHosts == null) {
+ this.nonProxyHosts = getEnvironmentVariableNonNull("no_proxy");
+ }
+ if (!this.nonProxyHosts.isEmpty()) {
+ system.setProperty(protocol + ".nonProxyHosts", this.nonProxyHosts);
+ }
+ } catch (MalformedURLException e) {
+ context.level(IdeLogLevel.WARNING)
+ .log(e, "Invalid {} proxy configuration detected with URL {}. Proxy configuration will be skipped.\n"
+ + "For further details, see " + PROXY_DOCUMENTATION_PAGE, protocol, proxyUrlString);
+ }
+ }
+
+ private String getProxyUrlFromEnvironmentVariable(String protocol) {
+
+ String proxyUrl = getEnvironmentVariableCaseInsensitive(protocol + "_proxy");
+ if (proxyUrl == null) {
+ if (this.allProxy == null) {
+ this.allProxy = getEnvironmentVariableNonNull("all_proxy");
+ }
+ if (!this.allProxy.isEmpty()) {
+ proxyUrl = this.allProxy;
+ }
+ }
+ return proxyUrl;
+ }
+
+ private String getEnvironmentVariableNonNull(String nameLowerCase) {
+
+ String value = getEnvironmentVariableCaseInsensitive(nameLowerCase);
+ if (value == null) {
+ return "";
+ } else {
+ return value.trim();
+ }
+ }
+
+ private String getEnvironmentVariableCaseInsensitive(String nameLowerCase) {
+
+ String value = getEnvironmentVariable(nameLowerCase);
+ if (value == null) {
+ value = getEnvironmentVariable(nameLowerCase.toUpperCase(Locale.ROOT));
+ }
+ return value;
+ }
+
+ private String getEnvironmentVariable(String name) {
+
+ String value = this.context.getSystem().getEnv(name);
+ if (value != null) {
+ this.context.trace("Found environment variable {}={}", name, value);
+ }
+ return value;
+ }
+
+}
diff --git a/cli/src/main/java/com/devonfw/tools/ide/network/ProxyConfig.java b/cli/src/main/java/com/devonfw/tools/ide/network/ProxyConfig.java
deleted file mode 100644
index 347750838..000000000
--- a/cli/src/main/java/com/devonfw/tools/ide/network/ProxyConfig.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.devonfw.tools.ide.network;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import com.devonfw.tools.ide.context.IdeContext;
-
-/**
- * Class responsible for parsing and storing the host and port information from a given proxy URL.
- */
-public class ProxyConfig {
-
- private final IdeContext context;
-
- private String host;
-
- private int port;
-
- ProxyConfig(String proxyUrl, IdeContext context) {
-
- this.context = context;
-
- try {
- URL url = new URL(proxyUrl);
- this.host = url.getHost();
- this.port = url.getPort();
- } catch (MalformedURLException e) {
- this.context.warning(ProxyContext.PROXY_FORMAT_WARNING_MESSAGE);
- }
- }
-
- /**
- * @return a {@link String} representing the host of the proxy
- */
- public String getHost() {
-
- return this.host;
- }
-
- /**
- * @return an {@code int} representing the port of the proxy
- */
- public int getPort() {
-
- return this.port;
- }
-}
diff --git a/cli/src/main/java/com/devonfw/tools/ide/network/ProxyContext.java b/cli/src/main/java/com/devonfw/tools/ide/network/ProxyContext.java
deleted file mode 100644
index c53af016d..000000000
--- a/cli/src/main/java/com/devonfw/tools/ide/network/ProxyContext.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.devonfw.tools.ide.network;
-
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-
-import com.devonfw.tools.ide.context.IdeContext;
-
-/**
- * Class for handling system proxy settings. This class is responsible for detecting and managing the proxy configurations for HTTP and HTTPS protocols based on
- * the system's environment variables.
- */
-public class ProxyContext {
-
- private final IdeContext context;
-
- private static final String HTTP_PROXY = "http_proxy";
-
- private static final String HTTPS_PROXY = "https_proxy";
-
- private static final String PROXY_DOCUMENTATION_PAGE = "https://github.com/devonfw/IDEasy/blob/main/documentation/proxy-support.adoc";
-
- static final String PROXY_FORMAT_WARNING_MESSAGE =
- "Proxy configuration detected, but the formatting appears to be incorrect. Proxy configuration will be skipped.\n"
- + "Please note that IDEasy can detect a proxy only if the corresponding environmental variables are properly formatted. "
- + "For further details, see " + PROXY_DOCUMENTATION_PAGE;
-
- final private ProxyConfig httpProxyConfig;
-
- final private ProxyConfig httpsProxyConfig;
-
- /**
- * Class to detect system proxy configurations
- *
- * @param context the {@link IdeContext}
- */
- public ProxyContext(IdeContext context) {
-
- this.context = context;
- this.httpProxyConfig = initializeProxyConfig(HTTP_PROXY);
- this.httpsProxyConfig = initializeProxyConfig(HTTPS_PROXY);
- }
-
- private ProxyConfig initializeProxyConfig(String proxyEnvVariable) {
-
- String proxyUrl = System.getenv(proxyEnvVariable);
- if (proxyUrl == null) {
- proxyUrl = System.getenv(proxyEnvVariable.toUpperCase());
- }
- return (proxyUrl != null && !proxyUrl.isEmpty()) ? new ProxyConfig(proxyUrl, this.context) : null;
- }
-
- /**
- * Retrieves the system proxy for a given URL.
- *
- * @param url The URL of the request for which to detect a proxy. This is used to determine the corresponding proxy based on the protocol.
- * @return A {@link Proxy} object representing the system proxy for the given URL, or {@link Proxy#NO_PROXY} if no valid proxy is found or if the proxy
- * configuration is invalid.
- */
- public Proxy getProxy(String url) {
-
- ProxyConfig proxyConfig = getProxyConfig(url);
- if (proxyConfig != null) {
- String proxyHost = proxyConfig.getHost();
- int proxyPort = proxyConfig.getPort();
-
- if (proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0 && proxyPort <= 65535) {
- InetSocketAddress proxyAddress = new InetSocketAddress(proxyHost, proxyPort);
- if (proxyAddress.isUnresolved()) {
- this.context.warning(ProxyContext.PROXY_FORMAT_WARNING_MESSAGE);
- return Proxy.NO_PROXY;
- }
- return new Proxy(Proxy.Type.HTTP, proxyAddress);
- }
- }
- return Proxy.NO_PROXY;
- }
-
- /**
- * Retrieves the appropriate {@link ProxyConfig} object based on the given request URL.
- *
- * @param url a {@link String} representing the URL for which the related proxy is to be determined
- * @return a {@link ProxyConfig} object with the correct settings, or {@code null} if the URL is malformed
- */
- public ProxyConfig getProxyConfig(String url) {
-
- if (url.startsWith("http://")) {
- return this.httpProxyConfig;
- } else if (url.startsWith("https://")) {
- return this.httpsProxyConfig;
- } else {
- this.context.warning("Download URL wrongly formatted: " + url);
- return null;
- }
- }
-}
-
diff --git a/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java b/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java
index 24cec551a..d0ab88f23 100644
--- a/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java
+++ b/cli/src/main/java/com/devonfw/tools/ide/process/ProcessContextImpl.java
@@ -172,27 +172,30 @@ public ProcessResult run(ProcessMode processMode) {
Process process = this.processBuilder.start();
- if (processMode == ProcessMode.DEFAULT_CAPTURE) {
- CompletableFuture> outFut = readInputStream(process.getInputStream());
- CompletableFuture> errFut = readInputStream(process.getErrorStream());
- out = outFut.get();
- err = errFut.get();
- }
+ try {
+ if (processMode == ProcessMode.DEFAULT_CAPTURE) {
+ CompletableFuture> outFut = readInputStream(process.getInputStream());
+ CompletableFuture> errFut = readInputStream(process.getErrorStream());
+ out = outFut.get();
+ err = errFut.get();
+ }
- int exitCode;
+ int exitCode;
- if (processMode.isBackground()) {
- exitCode = ProcessResult.SUCCESS;
- } else {
- exitCode = process.waitFor();
- }
-
- ProcessResult result = new ProcessResultImpl(exitCode, out, err);
+ if (processMode.isBackground()) {
+ exitCode = ProcessResult.SUCCESS;
+ } else {
+ exitCode = process.waitFor();
+ }
- performLogging(result, exitCode, interpreter);
+ ProcessResult result = new ProcessResultImpl(exitCode, out, err);
- return result;
+ performLogging(result, exitCode, interpreter);
+ return result;
+ } finally {
+ process.destroy();
+ }
} catch (CliProcessException | IllegalStateException e) {
// these exceptions are thrown from performLogOnError and we do not want to wrap them (see #593)
throw e;
diff --git a/cli/src/main/package/bin/ide b/cli/src/main/package/bin/ide
deleted file mode 100644
index 58ee8a3d0..000000000
--- a/cli/src/main/package/bin/ide
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env bash
-
-_IDEASY="$(dirname "${BASH_SOURCE}")/ideasy"
-if [ $# != 0 ]; then
- "${_IDEASY}" "$@"
- return_code=$?
- if [ $return_code != 0 ]; then
- echo -e "\n\033[91mError: IDEasy failed with exit code ${return_code}\033[91m" >&2
- unset _IDEASY
- return ${return_code}
- fi
-fi
-
-ide_env="$("${_IDEASY}" env --bash)"
-if [ $? = 0 ]; then
- eval "${ide_env}"
- if [ $# = 0 ]; then
- ide status
- echo "IDE environment variables have been set for ${IDE_HOME} in workspace ${WORKSPACE}"
- fi
-fi
-
-if [ "${OSTYPE}" = "cygwin" ]; then
- echo -e "\033[93m--- WARNING: CYGWIN IS NOT SUPPORTED ---\nCygwin console is not supported by IDEasy.\nConsider using the git terminal instead.\nIf you want to use Cygwin with IDEasy, you will have to configure it yourself.\nA few suggestions and caveats can be found here:\nhttps://github.com/devonfw/IDEasy/blob/main/documentation/cygwin.adoc\n\033[39m"
-fi
-
-unset _IDEASY
-unset ide_env
-unset return_code
diff --git a/cli/src/main/package/completion b/cli/src/main/package/completion
deleted file mode 100755
index 46b6e87b9..000000000
--- a/cli/src/main/package/completion
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-_ide_completion()
-{
- if [ -z "${COMP_WORDS[COMP_CWORD]}" ]; then
- COMPREPLY=( $(ideasy -q complete ${COMP_WORDS[@]:1} "") )
- else
- COMPREPLY=( $(ideasy -q complete ${COMP_WORDS[@]:1}) )
- fi
-}
-
-complete -F _ide_completion ide
diff --git a/cli/src/main/package/functions b/cli/src/main/package/functions
new file mode 100644
index 000000000..c5fdf0975
--- /dev/null
+++ b/cli/src/main/package/functions
@@ -0,0 +1,94 @@
+#!/usr/bin/env bash
+# this script should be sourced, shebang above only for syntax highlighting in editors
+function ide() {
+ local return_code
+ local ide_env
+ if [ $# != 0 ] && [ "$1" != "init" ]; then
+ ideasy ${IDE_OPTIONS} "$@"
+ return_code=$?
+ if [ $return_code != 0 ]; then
+ echo -e "\n\033[91mError: IDEasy failed with exit code ${return_code}\033[91m" >&2
+ return ${return_code}
+ fi
+ fi
+ ide_env="$(ideasy ${IDE_OPTIONS} env --bash)"
+ if [ $? = 0 ]; then
+ eval "${ide_env}"
+ if [ $# = 0 ]; then
+ ideasy ${IDE_OPTIONS} status
+ echo "IDE environment variables have been set for ${IDE_HOME} in workspace ${WORKSPACE}"
+ fi
+ fi
+ if [ "${OSTYPE}" = "cygwin" ] && [ "$1" != "init" ]; then
+ echo -e "\033[93m--- WARNING: CYGWIN IS NOT SUPPORTED ---\nCygwin console is not supported by IDEasy.\nConsider using the git terminal instead.\nIf you want to use Cygwin with IDEasy, you will have to configure it yourself.\nA few suggestions and caveats can be found here:\nhttps://github.com/devonfw/IDEasy/blob/main/documentation/cygwin.adoc\n\033[39m"
+ fi
+}
+
+function icd() {
+ if [ $# = 1 ] && [ "${1::1}" != "-" ]; then
+ cd $1 || return 1
+ ide init
+ return
+ elif [ $# -gt 2 ]; then
+ echo -e "\033[93mInvalid usage icd $*\033[39m" >&2
+ return 1
+ fi
+ if [ "$1" = "-p" ]; then
+ if [ -d "${IDE_ROOT}/$2" ]; then
+ cd "${IDE_ROOT}/$2"
+ ide init
+ return
+ else
+ echo -e "\033[93mNo such IDE project ${IDE_ROOT}/$2\033[39m" >&2
+ return 1
+ fi
+ fi
+ if [ ! -d "${IDE_HOME}" ]; then
+ ide init
+ fi
+ if [ $# = 0 ]; then
+ if [ -d "${IDE_HOME}" ]; then
+ cd "${IDE_HOME}"
+ return
+ fi
+ echo -e "\033[93mYou are not inside an IDE project: $PWD\033[39m" >&2
+ return 1
+ elif [ "$1" = "-w" ]; then
+ local wksp=$2
+ if [ "${wksp}" = "" ]; then
+ wksp=main
+ fi
+ if [ -d "${IDE_HOME}/workspaces/${wksp}" ]; then
+ cd "${IDE_HOME}/workspaces/${wksp}"
+ ide init
+ return
+ else
+ echo -e "\033[93mNo such IDE workspace ${IDE_HOME}/workspaces/${wksp}\033[39m" >&2
+ return 1
+ fi
+ fi
+}
+
+_ide_completion()
+{
+ if [ -z "${COMP_WORDS[COMP_CWORD]}" ]; then
+ COMPREPLY=( $(ideasy -q complete ${COMP_WORDS[@]:1} "") )
+ else
+ COMPREPLY=( $(ideasy -q complete ${COMP_WORDS[@]:1}) )
+ fi
+}
+
+if [ "${0/*\//}" = "zsh" ]; then
+ autoload -Uz compinit
+ compinit
+ autoload bashcompinit
+ bashcompinit
+fi
+
+if ! command -v ideasy &> /dev/null; then
+ export PATH="${PATH}:${IDE_ROOT}/_ide/bin"
+fi
+
+complete -F _ide_completion ide
+ide init
+
diff --git a/cli/src/main/package/setup b/cli/src/main/package/setup
index d7fa8828c..b1e90a4b5 100755
--- a/cli/src/main/package/setup
+++ b/cli/src/main/package/setup
@@ -6,34 +6,27 @@ function doSetupInConfigFile() {
echo "${cfg} not found - skipping."
return
fi
- if [ "${cfg}" = "~/.zshrc" ]; then
- if ! grep -q "compinit" "${cfg}"; then
- echo -e 'autoload -Uz compinit\ncompinit' >> "${cfg}"
- fi
- if ! grep -q "bashcompinit" "${cfg}"; then
- echo -e 'autoload bashcompinit\nbashcompinit' >> "${cfg}"
- fi
- fi
echo "Configuring IDEasy in ${cfg}."
- if ! grep -q "${AUTOCOMPLETION}" "${cfg}"; then
- echo -e "${AUTOCOMPLETION}" >> "${cfg}"
- fi
- if ! grep -q "alias ide=" "${cfg}"; then
- echo -e "alias ide=\"source ${PWD}/bin/ide\"" >> "${cfg}"
- echo -e "ide" >> "${cfg}"
- fi
if [ "${OSTYPE}" != "cygwin" ] && [ "${OSTYPE}" != "msys" ]; then
- if ! grep -q "IDE_ROOT" "${cfg}"
+ if ! grep -q "export IDE_ROOT=" "${cfg}"
then
- echo -e 'export IDE_ROOT="${PWD}"' >> "${cfg}"
+ echo "export IDE_ROOT=\"${IDE_ROOT}\"" >> "${cfg}"
fi
fi
+ if ! grep -q 'source "$IDE_ROOT/_ide/functions"' "${cfg}"; then
+ echo 'source "$IDE_ROOT/_ide/functions"' >> "${cfg}"
+ echo "ide init" >> "${cfg}"
+ fi
}
cd "$(dirname "${BASH_SOURCE:-$0}")" || exit 255
-echo "Setting up your IDEasy in ${PWD}"
-
-AUTOCOMPLETION="source ${PWD}/completion"
+if [ "${PWD/*\//}" != "_ide" ]; then
+ echo -e "\033[93mInvalid installation path $PWD - you need to install IDEasy to a folder named '_ide'.\033[39m" >&2
+fi
+echo "Setting up IDEasy in ${PWD}"
+cd ..
+export IDE_ROOT=${PWD}
+source "$IDE_ROOT/_ide/functions"
doSetupInConfigFile ~/.bashrc
doSetupInConfigFile ~/.zshrc
diff --git a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java
index 540940f8f..2d283b863 100644
--- a/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java
+++ b/cli/src/test/java/com/devonfw/tools/ide/context/AbstractIdeTestContext.java
@@ -13,6 +13,8 @@
import com.devonfw.tools.ide.environment.EnvironmentVariables;
import com.devonfw.tools.ide.environment.EnvironmentVariablesPropertiesFile;
import com.devonfw.tools.ide.environment.EnvironmentVariablesType;
+import com.devonfw.tools.ide.environment.IdeSystem;
+import com.devonfw.tools.ide.environment.IdeSystemTestImpl;
import com.devonfw.tools.ide.io.IdeProgressBar;
import com.devonfw.tools.ide.io.IdeProgressBarTestImpl;
import com.devonfw.tools.ide.log.IdeLogger;
@@ -128,6 +130,23 @@ protected AbstractEnvironmentVariables createSystemVariables() {
return super.createSystemVariables();
}
+ @Override
+ public IdeSystemTestImpl getSystem() {
+
+ if (this.system == null) {
+ this.system = IdeSystemTestImpl.ofSystemDefaults(this);
+ }
+ return (IdeSystemTestImpl) this.system;
+ }
+
+ /**
+ * @param system the new value of {@link #getSystem()}.
+ */
+ public void setSystem(IdeSystem system) {
+
+ this.system = system;
+ }
+
@Override
protected SystemPath computeSystemPath() {
diff --git a/cli/src/test/java/com/devonfw/tools/ide/environment/IdeSystemTestImpl.java b/cli/src/test/java/com/devonfw/tools/ide/environment/IdeSystemTestImpl.java
new file mode 100644
index 000000000..0486ce956
--- /dev/null
+++ b/cli/src/test/java/com/devonfw/tools/ide/environment/IdeSystemTestImpl.java
@@ -0,0 +1,59 @@
+package com.devonfw.tools.ide.environment;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import com.devonfw.tools.ide.log.IdeLogger;
+
+/**
+ * Extends {@link IdeSystemImpl} for testing. It will not modify your {@link System} and allows to modify environment variables for testing.
+ */
+public class IdeSystemTestImpl extends IdeSystemImpl {
+
+ /**
+ * @param logger the {@link IdeLogger}.
+ */
+ public IdeSystemTestImpl(IdeLogger logger) {
+
+ this(logger, new Properties(), new HashMap<>());
+ this.environmentVariables.put("PATH", System.getenv("PATH"));
+ }
+
+ /**
+ * @param logger the {@link IdeLogger}.
+ * @param systemProperties the {@link System#getProperties() system properties} for testing.
+ * @param environmentVariables the {@link System#getenv() environment variables} for testing.
+ */
+ public IdeSystemTestImpl(IdeLogger logger, Properties systemProperties,
+ Map environmentVariables) {
+
+ super(logger, systemProperties, environmentVariables);
+ }
+
+ /**
+ * @param key the name of the environment variable to mock.
+ * @param value the value of the environment variable to mock.
+ */
+ public void setEnv(String key, String value) {
+
+ this.environmentVariables.put(key, value);
+ }
+
+ /**
+ * @return the internal system {@link Properties}.
+ */
+ public Properties getProperties() {
+
+ return this.systemProperties;
+ }
+
+ /**
+ * @param logger the {@link IdeLogger}.
+ * @return a new instance of {@link IdeSystemTestImpl} initialized with {@link System} values but decoupled so changes do not affect {@link System}.
+ */
+ public static IdeSystemTestImpl ofSystemDefaults(IdeLogger logger) {
+
+ return new IdeSystemTestImpl(logger, new Properties(System.getProperties()), new HashMap<>(System.getenv()));
+ }
+}
diff --git a/cli/src/test/java/com/devonfw/tools/ide/network/NetworkProxyTest.java b/cli/src/test/java/com/devonfw/tools/ide/network/NetworkProxyTest.java
new file mode 100644
index 000000000..dfa7f531b
--- /dev/null
+++ b/cli/src/test/java/com/devonfw/tools/ide/network/NetworkProxyTest.java
@@ -0,0 +1,178 @@
+package com.devonfw.tools.ide.network;
+
+import org.junit.jupiter.api.Test;
+
+import com.devonfw.tools.ide.context.AbstractIdeContextTest;
+import com.devonfw.tools.ide.context.IdeTestContext;
+
+/**
+ * Test of {@link NetworkProxy}.
+ */
+public class NetworkProxyTest extends AbstractIdeContextTest {
+
+ private static final String PROXY_DOCUMENTATION_PAGE = "https://github.com/devonfw/IDEasy/blob/main/documentation/proxy-support.adoc";
+
+ /**
+ * Verifies that when the HTTP_PROXY variable contains a malformed URL, {@link NetworkProxy#configure()} does not configure proxy properties.
+ */
+ @Test
+ public void testHttpProxyMalformedUrl() {
+
+ // arrange
+ IdeTestContext context = new IdeTestContext();
+ NetworkProxy networkProxy = new NetworkProxy(context);
+ String invalidUrl = "htt:p//example.com";
+ context.getSystem().setEnv("HTTP_PROXY", invalidUrl);
+ context.getSystem().setEnv("no_proxy", ".foo.com,localhost");
+
+ // act
+ networkProxy.configure();
+
+ // assert
+ assertThat(context.getSystem().getProperties()).isEmpty();
+ assertThat(context).logAtWarning().hasMessageContaining("Invalid http proxy configuration detected with URL " + invalidUrl + ".");
+ assertThat(context).logAtWarning().hasMessageContaining(PROXY_DOCUMENTATION_PAGE);
+ }
+
+ /**
+ * Verifies that in an environment where no proxy variables are set, {@link NetworkProxy#configure()} does not configure proxy properties.
+ */
+ @Test
+ public void testNoProxy() {
+
+ // arrange
+ IdeTestContext context = new IdeTestContext();
+ NetworkProxy networkProxy = new NetworkProxy(context);
+
+ // act
+ networkProxy.configure();
+
+ // assert
+ assertThat(context.getSystem().getProperties()).isEmpty();
+ }
+
+ /**
+ * Verifies that in an environment where a HTTP_PROXY variable is set, {@link NetworkProxy#configure()} configures the according Java proxy properties.
+ */
+ @Test
+ public void testHttpProxyUpperCase() {
+
+ // arrange
+ IdeTestContext context = new IdeTestContext();
+ NetworkProxy networkProxy = new NetworkProxy(context);
+ context.getSystem().setEnv("HTTP_PROXY", "http://proxy.host.com:8888");
+ String noProxy = ".foo.com,localhost";
+ context.getSystem().setEnv("NO_PROXY", noProxy);
+
+ // act
+ networkProxy.configure();
+
+ // assert
+ assertThat(context.getSystem().getProperty("http.proxyHost")).isEqualTo("proxy.host.com");
+ assertThat(context.getSystem().getProperty("http.proxyPort")).isEqualTo("8888");
+ assertThat(context.getSystem().getProperty("http.nonProxyHosts")).isEqualTo(noProxy);
+ assertThat(context.getSystem().getProperties()).hasSize(3);
+ }
+
+ /**
+ * Verifies that in an environment where a http_proxy variable is set, {@link NetworkProxy#configure()} configures the according Java proxy properties.
+ */
+ @Test
+ public void testHttpProxyLowercase() {
+
+ // arrange
+ IdeTestContext context = new IdeTestContext();
+ NetworkProxy networkProxy = new NetworkProxy(context);
+ context.getSystem().setEnv("http_proxy", "http://proxy.host.com:8888");
+ String noProxy = ".foo.com,localhost";
+ context.getSystem().setEnv("no_proxy", noProxy);
+
+ // act
+ networkProxy.configure();
+
+ // assert
+ assertThat(context.getSystem().getProperty("http.proxyHost")).isEqualTo("proxy.host.com");
+ assertThat(context.getSystem().getProperty("http.proxyPort")).isEqualTo("8888");
+ assertThat(context.getSystem().getProperty("http.nonProxyHosts")).isEqualTo(noProxy);
+ assertThat(context.getSystem().getProperties()).hasSize(3);
+ }
+
+ /**
+ * Verifies that in an environment where a HTTPS_PROXY variable is set, {@link NetworkProxy#configure()} configures the according Java proxy properties.
+ * object.
+ */
+ @Test
+ public void testHttpsProxyUpperCase() {
+
+ // arrange
+ IdeTestContext context = new IdeTestContext();
+ NetworkProxy networkProxy = new NetworkProxy(context);
+ context.getSystem().setEnv("HTTPS_PROXY", "https://secure.proxy.com:8443");
+ String noProxy = ".foo.com,localhost";
+ context.getSystem().setEnv("NO_PROXY", noProxy);
+
+ // act
+ networkProxy.configure();
+
+ // assert
+ assertThat(context.getSystem().getProperty("https.proxyHost")).isEqualTo("secure.proxy.com");
+ assertThat(context.getSystem().getProperty("https.proxyPort")).isEqualTo("8443");
+ assertThat(context.getSystem().getProperty("https.nonProxyHosts")).isEqualTo(noProxy);
+ assertThat(context.getSystem().getProperties()).hasSize(3);
+ }
+
+ /**
+ * Verifies that in an environment where an all_proxy variable is set, {@link NetworkProxy#configure()} configures the according Java proxy properties.
+ * object.
+ */
+ @Test
+ public void testAllProxyLowerCase() {
+
+ // arrange
+ IdeTestContext context = new IdeTestContext();
+ NetworkProxy networkProxy = new NetworkProxy(context);
+ context.getSystem().setEnv("all_proxy", "https://secure.proxy.com");
+ String noProxy = ".foo.com,localhost";
+ context.getSystem().setEnv("no_proxy", noProxy);
+
+ // act
+ networkProxy.configure();
+
+ // assert
+ assertThat(context.getSystem().getProperty("http.proxyHost")).isEqualTo("secure.proxy.com");
+ assertThat(context.getSystem().getProperty("http.proxyPort")).isEqualTo("443");
+ assertThat(context.getSystem().getProperty("http.nonProxyHosts")).isEqualTo(noProxy);
+ assertThat(context.getSystem().getProperty("https.proxyHost")).isEqualTo("secure.proxy.com");
+ assertThat(context.getSystem().getProperty("https.proxyPort")).isEqualTo("443");
+ assertThat(context.getSystem().getProperty("https.nonProxyHosts")).isEqualTo(noProxy);
+ assertThat(context.getSystem().getProperties()).hasSize(6);
+ }
+
+ /**
+ * Verifies that in an environment where an ALL_PROXY variable is set, {@link NetworkProxy#configure()} configures the according Java proxy properties.
+ * object.
+ */
+ @Test
+ public void testAllProxyUpperCase() {
+
+ // arrange
+ IdeTestContext context = new IdeTestContext();
+ NetworkProxy networkProxy = new NetworkProxy(context);
+ context.getSystem().setEnv("ALL_PROXY", "http://proxy.company.com");
+ String noProxy = ".foo.com,localhost";
+ context.getSystem().setEnv("no_proxy", noProxy);
+
+ // act
+ networkProxy.configure();
+
+ // assert
+ assertThat(context.getSystem().getProperty("http.proxyHost")).isEqualTo("proxy.company.com");
+ assertThat(context.getSystem().getProperty("http.proxyPort")).isEqualTo("80");
+ assertThat(context.getSystem().getProperty("http.nonProxyHosts")).isEqualTo(noProxy);
+ assertThat(context.getSystem().getProperty("https.proxyHost")).isEqualTo("proxy.company.com");
+ assertThat(context.getSystem().getProperty("https.proxyPort")).isEqualTo("80");
+ assertThat(context.getSystem().getProperty("https.nonProxyHosts")).isEqualTo(noProxy);
+ assertThat(context.getSystem().getProperties()).hasSize(6);
+ }
+
+}
diff --git a/cli/src/test/java/com/devonfw/tools/ide/network/ProxyContextTest.java b/cli/src/test/java/com/devonfw/tools/ide/network/ProxyContextTest.java
deleted file mode 100644
index 9697a8957..000000000
--- a/cli/src/test/java/com/devonfw/tools/ide/network/ProxyContextTest.java
+++ /dev/null
@@ -1,204 +0,0 @@
-package com.devonfw.tools.ide.network;
-
-import java.net.Proxy;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-
-import com.devonfw.tools.ide.context.AbstractIdeContextTest;
-import com.devonfw.tools.ide.context.IdeTestContext;
-
-import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
-import uk.org.webcompere.systemstubs.jupiter.SystemStub;
-import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;
-
-/**
- * Test of {@link ProxyContext} and {@link ProxyConfig}.
- */
-@ExtendWith(SystemStubsExtension.class)
-public class ProxyContextTest extends AbstractIdeContextTest {
-
- private static final String PROJECT_PATH = "project/workspaces/foo-test/my-git-repo";
-
- private static final String HTTP_PROXY = "http://127.0.0.1:8888";
-
- private static final String HTTPS_PROXY = "https://127.0.0.1:8888";
-
- private static final String HTTP_PROXY_NO_HOST = "http://:8888";
- private static final String HTTP_PROXY_WRONG_HOST = "http://127.0.0.1wrongwrong:8888";
-
- private static final String HTTP_PROXY_WRONG_PROTOCOL = "wrong://127.0.0.1:8888";
-
- private static final String HTTP_PROXY_WRONG_FORMAT = "http://127.0.0.1:8888:wrong:wrong";
-
- private static final String PROXY_DOCUMENTATION_PAGE = "https://github.com/devonfw/IDEasy/blob/main/documentation/proxy-support.adoc";
-
- static final String PROXY_FORMAT_WARNING_MESSAGE =
- "Proxy configuration detected, but the formatting appears to be incorrect. Proxy configuration will be skipped.\n"
- + "Please note that IDEasy can detect a proxy only if the corresponding environmental variables are properly formatted. "
- + "For further details, see " + PROXY_DOCUMENTATION_PAGE;
-
- /**
- * Verifies that when the download URL is malformed, {@link ProxyContext#getProxy(String)} returns {@link Proxy#NO_PROXY}.
- */
- @Test
- public void testNoProxyMalformedUrl() {
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("htt:p//example.com");
-
- // assert
- assertThat(proxy).isEqualTo(Proxy.NO_PROXY);
- }
-
- /**
- * Verifies that in an environment where no proxy variables are set, {@link ProxyContext#getProxy(String)} returns {@link Proxy#NO_PROXY}.
- */
- @Test
- public void testNoProxy() {
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("https://example.com");
-
- // assert
- assertThat(proxy).isEqualTo(Proxy.NO_PROXY);
- }
-
- @SystemStub
- private final EnvironmentVariables environment = new EnvironmentVariables();
-
- /**
- * Verifies that in an environment where a http proxy variable is set, {@link ProxyContext#getProxy(String)} returns a correctly configured {@link Proxy}
- * object.
- */
- @Test
- public void testWithMockedHttpVar() {
-
- // arrange
- this.environment.set("HTTP_PROXY", HTTP_PROXY);
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("http://example.com");
-
- // assert
- assertThat("http:/" + proxy.address().toString()).isEqualTo(HTTP_PROXY);
- assertThat(proxy.type()).isEqualTo(Proxy.Type.HTTP);
- }
-
- /**
- * Verifies that in an environment where a http proxy variable (lowercase) is set, {@link ProxyContext#getProxy(String)} returns a correctly configured
- * {@link Proxy} object.
- */
- @Test
- public void testWithMockedHttpVarLowercase() {
-
- // arrange
- this.environment.set("http_proxy", HTTP_PROXY);
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("http://example.com");
-
- // assert
- assertThat("http:/" + proxy.address().toString()).isEqualTo(HTTP_PROXY);
- assertThat(proxy.type()).isEqualTo(Proxy.Type.HTTP);
- }
-
- /**
- * Verifies that in an environment where a https proxy variable is set, {@link ProxyContext#getProxy(String)} returns a correctly configured {@link Proxy}
- * object.
- */
- @Test
- public void testWithMockedHttpsVar() {
-
- // arrange
- this.environment.set("HTTPS_PROXY", HTTPS_PROXY);
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("https://example.com");
-
- // assert
- assertThat("https:/" + proxy.address().toString()).isEqualTo(HTTPS_PROXY);
- assertThat(proxy.type()).isEqualTo(Proxy.Type.HTTP);
- }
-
- /**
- * Verifies that in an environment where a http proxy variable is wrongly formatted, {@link ProxyContext#getProxy(String)} returns {@link Proxy#NO_PROXY}. A
- * warning message is displayed.
- */
- @Test
- public void testWithMockedHttpVarWrongFormat() {
-
- // arrange
- this.environment.set("HTTP_PROXY", HTTP_PROXY_WRONG_FORMAT);
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("http://example.com");
-
- // assert
- assertThat(proxy).isEqualTo(Proxy.NO_PROXY);
- assertThat(context).logAtWarning().hasMessage(PROXY_FORMAT_WARNING_MESSAGE);
- }
-
- /**
- * Verifies that in an environment where a http proxy variable is wrongly formatted, i.e. the host is empty, {@link ProxyContext#getProxy(String)} returns
- * {@link Proxy#NO_PROXY}.
- */
- @Test
- public void testWithMockedHttpVarNoHost() {
-
- // arrange
- this.environment.set("HTTP_PROXY", HTTP_PROXY_NO_HOST);
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("http://example.com");
-
- // assert
- assertThat(proxy).isEqualTo(Proxy.NO_PROXY);
- }
-
- /**
- * Verifies that in an environment where a http proxy variable is wrongly formatted, {@link ProxyContext#getProxy(String)} returns {@link Proxy#NO_PROXY}. A
- * warning message is displayed.
- */
- @Test
- public void testWithMockedHttpVarWrongHost() {
-
- // arrange
- this.environment.set("HTTP_PROXY", HTTP_PROXY_WRONG_HOST);
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("http://example.com");
-
- // assert
- assertThat(proxy).isEqualTo(Proxy.NO_PROXY);
- assertThat(context).logAtWarning().hasMessage(PROXY_FORMAT_WARNING_MESSAGE);
- }
-
- /**
- * Verifies that in an environment where a http proxy variable is wrongly formatted, {@link ProxyContext#getProxy(String)} returns {@link Proxy#NO_PROXY}. A
- * warning message is displayed.
- */
- @Test
- public void testWithMockedHttpVarWrongProtocol() {
-
- // arrange
- this.environment.set("HTTP_PROXY", HTTP_PROXY_WRONG_PROTOCOL);
-
- // act
- IdeTestContext context = newContext(PROJECT_BASIC, PROJECT_PATH, false);
- Proxy proxy = context.getProxyContext().getProxy("http://example.com");
-
- // assert
- assertThat(proxy).isEqualTo(Proxy.NO_PROXY);
- assertThat(context).logAtWarning().hasMessage(PROXY_FORMAT_WARNING_MESSAGE);
- }
-
-}
diff --git a/cli/src/test/java/com/devonfw/tools/ide/tool/jasypt/JasyptTest.java b/cli/src/test/java/com/devonfw/tools/ide/tool/jasypt/JasyptTest.java
index cfe6980b3..cba9cb5a5 100644
--- a/cli/src/test/java/com/devonfw/tools/ide/tool/jasypt/JasyptTest.java
+++ b/cli/src/test/java/com/devonfw/tools/ide/tool/jasypt/JasyptTest.java
@@ -1,20 +1,14 @@
package com.devonfw.tools.ide.tool.jasypt;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import com.devonfw.tools.ide.commandlet.InstallCommandlet;
import com.devonfw.tools.ide.context.AbstractIdeContextTest;
import com.devonfw.tools.ide.context.IdeTestContext;
-import uk.org.webcompere.systemstubs.environment.EnvironmentVariables;
-import uk.org.webcompere.systemstubs.jupiter.SystemStub;
-import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension;
-
/**
* Integration test of {@link Jasypt}.
*/
-@ExtendWith(SystemStubsExtension.class)
public class JasyptTest extends AbstractIdeContextTest {
private static final String JASYPT_OPTS = "custom_argument";
@@ -78,9 +72,6 @@ public void testJasyptRun() {
checkInstallation(context);
}
- @SystemStub
- private final EnvironmentVariables environment = new EnvironmentVariables();
-
/**
* Tests if {@link Jasypt} Commandlet is properly running with a user-defined JASYPT_OPTS env variable
*/
@@ -88,9 +79,8 @@ public void testJasyptRun() {
public void testJasyptRunWithCustomVariable() {
// arrange
- this.environment.set("JASYPT_OPTS", JASYPT_OPTS);
-
IdeTestContext context = newContext(PROJECT_JASYPT);
+ context.getSystem().setEnv("JASYPT_OPTS", JASYPT_OPTS);
Jasypt commandlet = new Jasypt(context);
commandlet.command.setValue(JasyptCommand.ENCRYPT);
diff --git a/documentation/proxy-support.adoc b/documentation/proxy-support.adoc
index 920ad8c71..9d0570b5f 100644
--- a/documentation/proxy-support.adoc
+++ b/documentation/proxy-support.adoc
@@ -1,23 +1,67 @@
-[[proxy-support.adoc]]
-= Proxy support
-
:toc:
toc::[]
-IDEasy provides built-in support for automatic HTTP and HTTPS proxy recognition.
+= Proxy support
+
+In order to be usable and acceptable world-wide and in enterprise contexts, it is required that IDEasy provides support for network proxies.
+In case you are working in a company and can only access the Internet via an HTTP proxy, we support your use-case and this page gives details how to make it work.
-[[proxy-support.adoc_Configuring-Proxy-settings]]
== Configuring Proxy Settings
To enable automatic proxy recognition, users need to set the appropriate environment variables in their system, or check if they are already set.
These variables should be formatted as follows, lowercase or uppercase:
-[source,bash]
-----
-http_proxy=http://:
-# e.g. http_proxy=http://127.0.0.1:8888
-https_proxy=https://:
-# e.g. https_proxy=https://127.0.0.1:8888
-----
+```
+# example values for a proxy configuration
+http_proxy=http://proxy.host.com:8888
+https_proxy=https://proxy.host.com:8443
+no_proxy=.domain.com,localhost
+```
+
+Many famous tools like `wget`, `curl`, etc. honor these variables and work behind a proxy this way.
+This also applies for IDEasy so in a standard case, it will work for you out of the box.
+However, in case it is not working, please read on to find solutions to configure IDEasy to your needs.
+
+== Advanced Proxy Configuration
+
+To support advanced proxy configuration, we introduced the link:variables.adoc[variable] `IDE_OPTIONS` that you can set on OS level or e.g. in your `~/.bashrc`.
+It allows to set arbitrary JVM options like https://docs.oracle.com/en/java/javase/21/core/java-networking.html#JSCOR-GUID-2C88D6BD-F278-4BD5-B0E5-F39B2BFAA840[proxy settings]
+as well as https://www.baeldung.com/java-custom-truststore[truststore settings] (see also https://docs.oracle.com/en/java/javase/21/docs/api/system-properties.html[Java system properties]).
+
+E.g. if you do not want to rely on the proxy environment variables above, you can also make this explicitly:
+
+```
+export IDE_OPTIONS="-Dhttps.proxyHost=proxy.host.com -Dhttps.proxyPort=8443
+```
+
+=== Authentication
+
+In some cases your network proxy may require authentication.
+Then you need to manually configure your account details like in the following example:
+
+```
+export IDE_OPTIONS="-Dhttp.proxyUser=$USERNAME -Dhttp.proxyPassword=«password»"
+```
+
+=== Truststore
+
+Some strange VPN tools have the bad habit to break up and sniff TLS encrypted connections.
+Therefore, they create their own TLS connection with a self-made certificate that is typically installed into the certificate trust store of the OS during installation.
+However, tools like Java or Firefox do not use the OS trust store but bring their own and therefore may reveal this hack.
+In IDEasy (or Eclipse Marketplace) you may therefore end up with the following error:
+
+```
+javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
+```
+
+So in other words, you may want to create a proper https://www.baeldung.com/java-keystore-truststore-difference#java-truststore[truststore] and configure IDEasy like this:
+
+```
+export IDE_OPTIONS="-Djavax.net.ssl.trustStore=/path/to/another/truststore.p12 -Djavax.net.ssl.trustStorePassword=changeit"
+```
-IDEasy utilizes these environment variables to detect and configure proxy settings during runtime.
+Sorry, that we cannot support you automatically on this use-case.
+Ask your VPN tool vendor for support and why this is all required.
+In general encryption should be end-to-end and your data should be protected.
+You may also want to visit https://badssl.com/ while your VPN tool is active and click the certificate tests like https://pinning-test.badssl.com/[pinning-test].
+If you then do not get an error in your browser (like "Secure connection failed") but a red warning page, your VPN tools is putting you at risk with breaking your TLS connections.
diff --git a/documentation/variables.adoc b/documentation/variables.adoc
index ef203146c..cf3b9d3a3 100644
--- a/documentation/variables.adoc
+++ b/documentation/variables.adoc
@@ -15,6 +15,7 @@ Please note that we are trying to minimize any potential side-effect from `IDEas
|*Variable*|*Value*|*Meaning*
|`IDE_ROOT`|e.g. `/projects/` or `C:\projects`|The installation root directory of `IDEasy` - see link:structure.adoc[structure] for details.
|`IDE_HOME`|e.g. `/projects/my-project`|The top level directory of your `IDEasy` project.
+|`IDE_OPTIONS`|`-`|General options that will be applied to each call of `IDEasy`. Should typically be used for JVM options like link:proxy-support.adoc[proxy-support].
|`PATH`|`$IDE_HOME/software/java:...:$PATH`|You system path is adjusted by `ide` link:cli.adoc[command].
|`HOME_DIR`|`~`|The platform independent home directory of the current user. In some edge-cases (e.g. in cygwin) this differs from `~` to ensure a central home directory for the user on a single machine in any context or environment.
|`IDE_TOOLS`|`(java mvn node npm)`|List of tools that should be installed by default on project creation.
diff --git a/pom.xml b/pom.xml
index beeccff3e..fc6b88b72 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,18 +35,6 @@
3.24.2
test
-
- org.mockito
- mockito-core
- 5.10.0
- test
-
-
- uk.org.webcompere
- system-stubs-jupiter
- 2.1.3
- test
-