diff --git a/plugin/META-INF/MANIFEST.MF b/plugin/META-INF/MANIFEST.MF
index dead985e5..9ff16a348 100644
--- a/plugin/META-INF/MANIFEST.MF
+++ b/plugin/META-INF/MANIFEST.MF
@@ -28,41 +28,46 @@ Require-Bundle: org.eclipse.core.runtime;bundle-version="3.31.0",
org.apache.commons.logging;bundle-version="1.2.0",
slf4j.api;bundle-version="2.0.13",
org.apache.commons.lang3;bundle-version="3.14.0"
-Bundle-Classpath: .,
- target/dependency/annotations-2.28.26.jar,
- target/dependency/apache-client-2.28.26.jar,
- target/dependency/auth-2.28.26.jar,
- target/dependency/aws-core-2.28.26.jar,
- target/dependency/aws-json-protocol-2.28.26.jar,
- target/dependency/checksums-2.28.26.jar,
- target/dependency/checksums-spi-2.28.26.jar,
- target/dependency/cognitoidentity-2.28.26.jar,
- target/dependency/commons-codec-1.17.1.jar,
- target/dependency/endpoints-spi-2.28.26.jar,
- target/dependency/http-auth-2.28.26.jar,
- target/dependency/http-auth-aws-2.28.26.jar,
- target/dependency/http-auth-aws-eventstream-2.28.26.jar,
- target/dependency/http-auth-spi-2.28.26.jar,
- target/dependency/http-client-spi-2.28.26.jar,
- target/dependency/httpclient-4.5.14.jar,
- target/dependency/httpcore-4.4.16.jar,
- target/dependency/identity-spi-2.28.26.jar,
- target/dependency/jackson-annotations-2.17.2.jar,
- target/dependency/jackson-core-2.17.2.jar,
- target/dependency/jackson-databind-2.17.2.jar,
- target/dependency/jakarta.inject-api-2.0.1.jar,
- target/dependency/json-utils-2.28.26.jar,
- target/dependency/maven-artifact-3.9.9.jar,
- target/dependency/metrics-spi-2.28.26.jar,
- target/dependency/netty-nio-client-2.28.26.jar,
- target/dependency/nimbus-jose-jwt-9.41.2.jar,
- target/dependency/profiles-2.28.26.jar,
- target/dependency/protocol-core-2.28.26.jar,
- target/dependency/reactive-streams-1.0.4.jar,
- target/dependency/regions-2.28.26.jar,
- target/dependency/retries-2.28.26.jar,
- target/dependency/retries-spi-2.28.26.jar,
- target/dependency/rxjava-3.1.5.jar,
- target/dependency/sdk-core-2.28.26.jar,
- target/dependency/third-party-jackson-core-2.28.26.jar,
- target/dependency/utils-2.28.26.jar
+Bundle-Classpath: target/classes/,
+ target/dependency/annotations.jar,
+ target/dependency/apache-client.jar,
+ target/dependency/auth.jar,
+ target/dependency/aws-core.jar,
+ target/dependency/aws-json-protocol.jar,
+ target/dependency/checksums-spi.jar,
+ target/dependency/checksums.jar,
+ target/dependency/cognitoidentity.jar,
+ target/dependency/commons-codec.jar,
+ target/dependency/delight-rhino-sandbox.jar,
+ target/dependency/endpoints-spi.jar,
+ target/dependency/http-auth-aws-eventstream.jar,
+ target/dependency/http-auth-aws.jar,
+ target/dependency/http-auth-spi.jar,
+ target/dependency/http-auth.jar,
+ target/dependency/http-client-spi.jar,
+ target/dependency/httpclient.jar,
+ target/dependency/httpcore.jar,
+ target/dependency/identity-spi.jar,
+ target/dependency/jackson-annotations.jar,
+ target/dependency/jackson-core.jar,
+ target/dependency/jackson-databind.jar,
+ target/dependency/jakarta.inject-api.jar,
+ target/dependency/jna-platform.jar,
+ target/dependency/jna.jar,
+ target/dependency/json-utils.jar,
+ target/dependency/maven-artifact.jar,
+ target/dependency/metrics-spi.jar,
+ target/dependency/netty-nio-client.jar,
+ target/dependency/nimbus-jose-jwt.jar,
+ target/dependency/profiles.jar,
+ target/dependency/protocol-core.jar,
+ target/dependency/proxy-vole.jar,
+ target/dependency/reactive-streams.jar,
+ target/dependency/regions.jar,
+ target/dependency/retries-spi.jar,
+ target/dependency/retries.jar,
+ target/dependency/rxjava.jar,
+ target/dependency/sdk-core.jar,
+ target/dependency/slf4j-api.jar,
+ target/dependency/third-party-jackson-core.jar,
+ target/dependency/utils.jar
diff --git a/plugin/pom.xml b/plugin/pom.xml
index 606bf886e..5ec2d85ad 100644
--- a/plugin/pom.xml
+++ b/plugin/pom.xml
@@ -42,21 +42,16 @@
-
- io.reactivex.rxjava3
- rxjava
- 3.1.5
-
+
+ io.reactivex.rxjava3
+ rxjava
+ 3.1.5
+
jakarta.inject
jakarta.inject-api
2.0.1
-
- io.reactivex.rxjava3
- rxjava
- 3.1.5
-
com.fasterxml.jackson.core
jackson-databind
@@ -106,6 +101,11 @@
maven-artifact
3.9.9
+
+ org.bidib.com.github.markusbernhardt
+ proxy-vole
+ 1.1.6
+
org.junit.jupiter
junit-jupiter
@@ -118,7 +118,7 @@
test
-
+
src
tst
@@ -148,8 +148,24 @@
copy-dependencies
+ runtime
+ true
${project.build.directory}/dependency
- io.reactivex,software.amazon.awssdk,com.fasterxml.jackson,com.nimbusds,jakarta.inject,commons-codec,org.apache.httpcomponents,org.reactivestreams,org.apache.maven
+
+ io.reactivex,
+ software.amazon.awssdk,
+ com.fasterxml.jackson,
+ com.nimbusds,jakarta.inject,
+ commons-codec,
+ org.apache.httpcomponents,
+ org.reactivestreams,
+ org.apache.maven,
+ org.bidib.com.github.markusbernhardt,
+ net.java.dev.jna,
+ org.ini4j,
+ org.javadelight,
+ org.slf4j
+
diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/ChatTheme.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/ChatTheme.java
index 1c031f598..6308426dd 100644
--- a/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/ChatTheme.java
+++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/ChatTheme.java
@@ -100,6 +100,8 @@ private String getCssForDarkTheme() {
// Card
themeMap.put(QChatCssVariable.CardBackground, cardBackgroundColor);
+ themeMap.put(QChatCssVariable.LineHeight, "1.25em");
+
return getCss(themeMap);
}
@@ -150,6 +152,8 @@ private String getCssForLightTheme() {
// Card
themeMap.put(QChatCssVariable.CardBackground, cardBackgroundColor);
+ themeMap.put(QChatCssVariable.LineHeight, "1.25em");
+
return getCss(themeMap);
}
diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariable.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariable.java
index a57c7ce26..14bcd1b38 100644
--- a/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariable.java
+++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariable.java
@@ -44,7 +44,10 @@ public enum QChatCssVariable {
AlternateForeground("--mynah-color-alternate-reverse"),
// Card
- CardBackground("--mynah-card-bg");
+ CardBackground("--mynah-card-bg"),
+
+ // Line height
+ LineHeight("--mynah-line-height");
private String value;
diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/connection/QLspConnectionProvider.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/connection/QLspConnectionProvider.java
index 9da462cfb..1ca8a6d36 100644
--- a/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/connection/QLspConnectionProvider.java
+++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/connection/QLspConnectionProvider.java
@@ -44,10 +44,10 @@ public QLspConnectionProvider() throws IOException {
@Override
protected final void addEnvironmentVariables(final Map env) {
- String httpsProxyPreference = ProxyUtil.getHttpsProxyUrl();
+ String httpsProxyUrl = ProxyUtil.getHttpsProxyUrl();
String caCertPreference = Activator.getDefault().getPreferenceStore().getString(AmazonQPreferencePage.CA_CERT);
- if (!StringUtils.isEmpty(httpsProxyPreference)) {
- env.put("HTTPS_PROXY", httpsProxyPreference);
+ if (!StringUtils.isEmpty(httpsProxyUrl)) {
+ env.put("HTTPS_PROXY", httpsProxyUrl);
}
if (!StringUtils.isEmpty(caCertPreference)) {
env.put("NODE_EXTRA_CA_CERTS", caCertPreference);
diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/manager/fetcher/VersionManifestFetcher.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/manager/fetcher/VersionManifestFetcher.java
index fc546669e..81a4c7b72 100644
--- a/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/manager/fetcher/VersionManifestFetcher.java
+++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/lsp/manager/fetcher/VersionManifestFetcher.java
@@ -32,6 +32,7 @@
import software.aws.toolkits.eclipse.amazonq.util.HttpClientFactory;
import software.aws.toolkits.eclipse.amazonq.util.ObjectMapperFactory;
import software.aws.toolkits.eclipse.amazonq.util.PluginUtils;
+import software.aws.toolkits.eclipse.amazonq.util.ThreadingUtils;
import software.aws.toolkits.eclipse.amazonq.util.ToolkitNotification;
import software.aws.toolkits.telemetry.TelemetryDefinitions.ManifestLocation;
import software.aws.toolkits.telemetry.TelemetryDefinitions.Result;
@@ -85,11 +86,25 @@ public Optional fetch() {
return latestManifest;
} catch (Exception e) {
if (e.getCause() instanceof SSLHandshakeException) {
- Display.getCurrent().asyncExec(() -> {
- AbstractNotificationPopup notification = new ToolkitNotification(Display.getCurrent(),
- Constants.IDE_SSL_HANDSHAKE_TITLE,
- Constants.IDE_SSL_HANDSHAKE_BODY);
- notification.open();
+ ThreadingUtils.executeAsyncTask(() -> {
+ Display display = null;
+ while (display == null) {
+ display = Display.getDefault();
+ if (display == null) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException interrupted) {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ }
+ }
+ display.asyncExec(() -> {
+ AbstractNotificationPopup notification = new ToolkitNotification(Display.getCurrent(),
+ Constants.IDE_SSL_HANDSHAKE_TITLE,
+ Constants.IDE_SSL_HANDSHAKE_BODY);
+ notification.open();
+ });
});
}
Activator.getLogger().error("Error fetching manifest from remote location", e);
diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/telemetry/service/DefaultTelemetryService.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/telemetry/service/DefaultTelemetryService.java
index 3f1c9928d..0d813cab8 100644
--- a/plugin/src/software/aws/toolkits/eclipse/amazonq/telemetry/service/DefaultTelemetryService.java
+++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/telemetry/service/DefaultTelemetryService.java
@@ -14,6 +14,7 @@
import javax.net.ssl.SSLContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.impl.client.SystemDefaultCredentialsProvider;
import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
@@ -141,7 +142,7 @@ private static ToolkitTelemetryClient createDefaultTelemetryClient(final Region
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier()
);
- var proxyUrl = ProxyUtil.getHttpsProxyUrl();
+ var proxyUrl = ProxyUtil.getHttpsProxyUrlForEndpoint(endpoint);
var httpClientBuilder = ApacheHttpClient.builder();
if (!StringUtils.isEmpty(proxyUrl)) {
httpClientBuilder.proxyConfiguration(ProxyConfiguration.builder()
@@ -151,7 +152,9 @@ private static ToolkitTelemetryClient createDefaultTelemetryClient(final Region
httpClientBuilder.socketFactory(sslSocketFactory);
- SdkHttpClient sdkHttpClient = httpClientBuilder.build();
+ SdkHttpClient sdkHttpClient = httpClientBuilder
+ .credentialsProvider(new SystemDefaultCredentialsProvider())
+ .build();
CognitoIdentityClient cognitoClient = CognitoIdentityClient.builder()
.credentialsProvider(AnonymousCredentialsProvider.create())
.region(region)
diff --git a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/ProxyUtil.java b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/ProxyUtil.java
index a9b41a7ea..c1b777c10 100644
--- a/plugin/src/software/aws/toolkits/eclipse/amazonq/util/ProxyUtil.java
+++ b/plugin/src/software/aws/toolkits/eclipse/amazonq/util/ProxyUtil.java
@@ -4,91 +4,203 @@
package software.aws.toolkits.eclipse.amazonq.util;
import java.io.FileInputStream;
+import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.ProxySelector;
import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
import org.eclipse.mylyn.commons.ui.dialogs.AbstractNotificationPopup;
import org.eclipse.swt.widgets.Display;
+import com.github.markusbernhardt.proxy.ProxySearch;
+
import software.amazon.awssdk.utils.StringUtils;
import software.aws.toolkits.eclipse.amazonq.plugin.Activator;
import software.aws.toolkits.eclipse.amazonq.preferences.AmazonQPreferencePage;
public final class ProxyUtil {
+ private static final String DEFAULT_PROXY_ENDPOINT = "https://amazonaws.com";
+ private static volatile boolean hasSeenInvalidProxyNotification;
- private static boolean hasSeenInvalidProxyNotification;
+ private static ProxySelector proxySelector;
- private ProxyUtil() {
- // Prevent initialization
- }
+ private ProxyUtil() { } // Prevent initialization
public static String getHttpsProxyUrl() {
- return getHttpsProxyUrl(System.getenv("HTTPS_PROXY"),
- Activator.getDefault().getPreferenceStore().getString(AmazonQPreferencePage.HTTPS_PROXY));
+ return getHttpsProxyUrlForEndpoint(DEFAULT_PROXY_ENDPOINT);
}
- protected static String getHttpsProxyUrl(final String envVarValue, final String prefValue) {
- String httpsProxy = envVarValue;
- if (!StringUtils.isEmpty(prefValue)) {
- httpsProxy = prefValue;
- }
+ public static String getHttpsProxyUrlForEndpoint(final String endpointUrl) {
try {
- if (!StringUtils.isEmpty(httpsProxy)) {
- URI.create(httpsProxy);
- }
- } catch (IllegalArgumentException e) {
- if (!hasSeenInvalidProxyNotification) {
- hasSeenInvalidProxyNotification = true;
- Display.getDefault().asyncExec(() -> {
- AbstractNotificationPopup notification = new ToolkitNotification(Display.getCurrent(),
- Constants.INVALID_PROXY_CONFIGURATION_TITLE,
- Constants.INVALID_PROXY_CONFIGURATION_BODY);
- notification.open();
- });
+ String proxyPrefUrl = getHttpsProxyPreferenceUrl();
+ if (!StringUtils.isEmpty(proxyPrefUrl)) {
+ return proxyPrefUrl;
}
+ } catch (MalformedURLException e) {
+ showInvalidProxyNotification();
+ return null;
+ }
+
+ if (StringUtils.isEmpty(endpointUrl)) {
+ return null;
+ }
+
+ URI endpointUri;
+ try {
+ endpointUri = new URI(endpointUrl);
+ } catch (URISyntaxException e) {
+ Activator.getLogger().error("Could not parse endpoint for proxy configuration: " + endpointUrl, e);
return null;
}
- return httpsProxy;
+
+ return getProxyUrlFromSelector(getProxySelector(), endpointUri);
+ }
+
+ private static String getProxyUrlFromSelector(final ProxySelector proxySelector, final URI endpointUri) {
+ if (proxySelector == null) {
+ return null;
+ }
+
+ var proxies = proxySelector.select(endpointUri);
+ if (proxies == null || proxies.isEmpty()) {
+ return null;
+ }
+
+ return proxies.stream()
+ .filter(p -> p.type() != Proxy.Type.DIRECT)
+ .findFirst()
+ .map(proxy -> createProxyUrl(proxy, endpointUri))
+ .orElseGet(() -> {
+ Activator.getLogger().info("No non-DIRECT proxies found for endpoint: " + endpointUri);
+ return null;
+ });
+ }
+
+ private static String createProxyUrl(final Proxy proxy, final URI endpointUri) {
+ if (!(proxy.address() instanceof InetSocketAddress addr)) {
+ return null;
+ }
+
+ String scheme = determineProxyScheme(proxy.type(), endpointUri);
+ if (scheme == null) {
+ return null;
+ }
+
+ String proxyUrl = String.format("%s://%s:%d", scheme, addr.getHostString(), addr.getPort());
+ Activator.getLogger().info("Using proxy URL: " + proxyUrl + " for endpoint: " + endpointUri);
+ return proxyUrl;
+ }
+
+ private static String determineProxyScheme(final Proxy.Type proxyType, final URI endpointUri) {
+ return switch (proxyType) {
+ case HTTP -> "http";
+ case SOCKS -> "socks";
+ default -> null;
+ };
+ }
+
+ protected static String getHttpsProxyPreferenceUrl() throws MalformedURLException {
+ String prefValue = Activator.getDefault().getPreferenceStore()
+ .getString(AmazonQPreferencePage.HTTPS_PROXY);
+
+ if (StringUtils.isEmpty(prefValue)) {
+ return null;
+ }
+
+ new URL(prefValue); // Validate URL format
+ return prefValue;
+ }
+
+ private static void showInvalidProxyNotification() {
+ if (!hasSeenInvalidProxyNotification) {
+ hasSeenInvalidProxyNotification = true;
+ Display.getDefault().asyncExec(() -> {
+ AbstractNotificationPopup notification = new ToolkitNotification(
+ Display.getCurrent(),
+ Constants.INVALID_PROXY_CONFIGURATION_TITLE,
+ Constants.INVALID_PROXY_CONFIGURATION_BODY
+ );
+ notification.open();
+ });
+ }
}
public static SSLContext getCustomSslContext() {
+ String customCertPath = getCustomCertPath();
+ if (StringUtils.isEmpty(customCertPath)) {
+ return null;
+ }
+
try {
- String customCertPath = System.getenv("NODE_EXTRA_CA_CERTS");
- String caCertPreference = Activator.getDefault().getPreferenceStore().getString(AmazonQPreferencePage.CA_CERT);
- if (!StringUtils.isEmpty(caCertPreference)) {
- customCertPath = caCertPreference;
- }
+ return createSslContextWithCustomCert(customCertPath);
+ } catch (Exception e) {
+ Activator.getLogger().error("Failed to set up SSL context. Additional certs will not be used.", e);
+ return null;
+ }
+ }
+
+ private static String getCustomCertPath() {
+ String caCertPreference = Activator.getDefault().getPreferenceStore().getString(AmazonQPreferencePage.CA_CERT);
+ return !StringUtils.isEmpty(caCertPreference) ? caCertPreference : System.getenv("NODE_EXTRA_CA_CERTS");
+ }
- if (customCertPath != null && !customCertPath.isEmpty()) {
- CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
- X509Certificate cert;
+ private static SSLContext createSslContextWithCustomCert(final String certPath) throws Exception {
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init((KeyStore) null);
- try (FileInputStream fis = new FileInputStream(customCertPath)) {
- cert = (X509Certificate) certificateFactory.generateCertificate(fis);
+ KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keyStore.load(null, null);
+
+ for (TrustManager tm : tmf.getTrustManagers()) {
+ if (tm instanceof X509TrustManager) {
+ X509TrustManager xtm = (X509TrustManager) tm;
+ for (X509Certificate cert : xtm.getAcceptedIssuers()) {
+ keyStore.setCertificateEntry(cert.getSubjectX500Principal().getName(), cert);
}
+ }
+ }
- KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- keyStore.load(null, null);
- keyStore.setCertificateEntry("custom-cert", cert);
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ X509Certificate cert;
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(keyStore);
+ try (FileInputStream fis = new FileInputStream(certPath)) {
+ cert = (X509Certificate) certificateFactory.generateCertificate(fis);
+ }
- SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
- sslContext.init(null, tmf.getTrustManagers(), null);
- Activator.getLogger().info("Picked up custom CA cert.");
+ keyStore.setCertificateEntry("custom-cert", cert);
- return sslContext;
+ TrustManagerFactory customTmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ customTmf.init(keyStore);
+
+ SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
+ sslContext.init(null, customTmf.getTrustManagers(), null);
+ Activator.getLogger().info("Picked up custom CA cert.");
+
+ return sslContext;
+ }
+
+ static synchronized ProxySelector getProxySelector() {
+ if (proxySelector == null) {
+ ProxySearch proxySearch = new ProxySearch();
+ proxySearch.addStrategy(ProxySearch.Strategy.ENV_VAR);
+ proxySearch.addStrategy(ProxySearch.Strategy.JAVA);
+ proxySearch.addStrategy(ProxySearch.Strategy.OS_DEFAULT);
+ if (System.getProperty("os.name").toLowerCase().contains("windows")) {
+ proxySearch.addStrategy(ProxySearch.Strategy.IE);
}
- } catch (Exception e) {
- Activator.getLogger().error("Failed to set up SSL context. Additional certs will not be used.", e);
+ proxySelector = proxySearch.getProxySelector();
}
- return null;
+ return proxySelector;
}
-
}
diff --git a/plugin/tst/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariableTest.java b/plugin/tst/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariableTest.java
index 6ec137cfc..45ae883ef 100644
--- a/plugin/tst/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariableTest.java
+++ b/plugin/tst/software/aws/toolkits/eclipse/amazonq/chat/models/QChatCssVariableTest.java
@@ -14,7 +14,7 @@ public class QChatCssVariableTest {
@Test
void testEnumValues() {
- assertEquals(27, QChatCssVariable.values().length);
+ assertEquals(28, QChatCssVariable.values().length);
}
@Test
@@ -72,6 +72,11 @@ void testCardValues() {
assertEquals("--mynah-card-bg", QChatCssVariable.CardBackground.getValue());
}
+ @Test
+ void testLineHeighValues() {
+ assertEquals("--mynah-line-height", QChatCssVariable.LineHeight.getValue());
+ }
+
@Test
void testInvalidEnum() {
assertThrows(IllegalArgumentException.class, () -> QChatCssVariable.valueOf("NonExistentVariable"));
diff --git a/plugin/tst/software/aws/toolkits/eclipse/amazonq/util/ProxyUtilTest.java b/plugin/tst/software/aws/toolkits/eclipse/amazonq/util/ProxyUtilTest.java
index c9e5e983e..1525172eb 100644
--- a/plugin/tst/software/aws/toolkits/eclipse/amazonq/util/ProxyUtilTest.java
+++ b/plugin/tst/software/aws/toolkits/eclipse/amazonq/util/ProxyUtilTest.java
@@ -3,58 +3,134 @@
package software.aws.toolkits.eclipse.amazonq.util;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.MockedStatic;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.swt.widgets.Display;
+
+import software.aws.toolkits.eclipse.amazonq.extensions.implementation.ActivatorStaticMockExtension;
+import software.aws.toolkits.eclipse.amazonq.plugin.Activator;
+import software.aws.toolkits.eclipse.amazonq.preferences.AmazonQPreferencePage;
+
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.util.Arrays;
+import java.util.Collections;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
-import org.eclipse.swt.widgets.Display;
+public final class ProxyUtilTest {
+
+ @RegisterExtension
+ private static ActivatorStaticMockExtension activatorStaticMockExtension = new ActivatorStaticMockExtension();
-class ProxyUtilTest {
+ private IPreferenceStore preferenceStore;
+ private ProxySelector proxySelector;
+
+ @BeforeEach
+ void setUp() {
+ preferenceStore = mock(IPreferenceStore.class);
+ proxySelector = mock(ProxySelector.class);
+
+ Activator activatorMock = activatorStaticMockExtension.getMock(Activator.class);
+ when(activatorMock.getPreferenceStore()).thenReturn(preferenceStore);
+ }
@Test
- void testNoProxyConfigReturnsNull() {
- assertEquals(null, ProxyUtil.getHttpsProxyUrl(null, null));
+ void testNoProxyConfigurationReturnsNull() {
+ when(preferenceStore.getString(AmazonQPreferencePage.HTTPS_PROXY)).thenReturn("");
+ try (MockedStatic proxyUtilMock = mockStatic(ProxyUtil.class, CALLS_REAL_METHODS)) {
+ proxyUtilMock.when(ProxyUtil::getProxySelector).thenReturn(proxySelector);
+ when(proxySelector.select(any())).thenReturn(Collections.emptyList());
+
+ assertNull(ProxyUtil.getHttpsProxyUrl());
+ }
}
@Test
- void testEnvVarProxyUrl() {
- String mockUrl = "http://foo.com:8888";
- assertEquals(mockUrl, ProxyUtil.getHttpsProxyUrl(mockUrl, null));
+ void testPreferenceProxyUrlTakesPrecedence() {
+ String preferenceUrl = "http://preference.proxy:8888";
+ when(preferenceStore.getString(AmazonQPreferencePage.HTTPS_PROXY)).thenReturn(preferenceUrl);
+
+ assertEquals(preferenceUrl, ProxyUtil.getHttpsProxyUrlForEndpoint("https://foo.com"));
}
@Test
- void testPreferenceProxyUrl() {
- String mockUrl = "http://foo.com:8888";
- assertEquals(mockUrl, ProxyUtil.getHttpsProxyUrl(null, mockUrl));
+ void testSystemProxyConfiguration() {
+ when(preferenceStore.getString(AmazonQPreferencePage.HTTPS_PROXY)).thenReturn("");
+
+ try (MockedStatic proxyUtilMock = mockStatic(ProxyUtil.class, CALLS_REAL_METHODS)) {
+ proxyUtilMock.when(ProxyUtil::getProxySelector).thenReturn(proxySelector);
+
+ Proxy httpProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080));
+ when(proxySelector.select(any())).thenReturn(Arrays.asList(httpProxy));
+
+ assertEquals("http://proxy.example.com:8080", ProxyUtil.getHttpsProxyUrlForEndpoint("https://foo.com"));
+ }
}
@Test
- void testPreferenceProxyUrlPrecedence() {
- String mockUrl = "http://foo.com:8888";
- assertEquals(mockUrl, ProxyUtil.getHttpsProxyUrl("http://bar.com:8888", mockUrl));
+ void testSocksProxyConfiguration() {
+ when(preferenceStore.getString(AmazonQPreferencePage.HTTPS_PROXY)).thenReturn("");
+
+ try (MockedStatic proxyUtilMock = mockStatic(ProxyUtil.class, CALLS_REAL_METHODS)) {
+ proxyUtilMock.when(ProxyUtil::getProxySelector).thenReturn(proxySelector);
+
+ Proxy socksProxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("socks.example.com", 1080));
+ when(proxySelector.select(any())).thenReturn(Arrays.asList(socksProxy));
+
+ assertEquals("socks://socks.example.com:1080", ProxyUtil.getHttpsProxyUrlForEndpoint("https://foo.com"));
+ }
}
@Test
- void testEnvVarInvalidProxyUrl() {
+ void testInvalidPreferenceProxyUrl() {
+ when(preferenceStore.getString(AmazonQPreferencePage.HTTPS_PROXY)).thenReturn("invalid:url");
+
try (MockedStatic displayMock = mockStatic(Display.class)) {
Display mockDisplay = mock(Display.class);
displayMock.when(Display::getDefault).thenReturn(mockDisplay);
- String mockUrl = "127.0.0.1:8000";
- assertEquals(null, ProxyUtil.getHttpsProxyUrl(mockUrl, null));
+ when(Display.getCurrent()).thenReturn(mockDisplay);
+
+ assertNull(ProxyUtil.getHttpsProxyUrlForEndpoint("https://foo.com"));
}
}
@Test
- void testPreferenceInvalidProxyUrl() {
- try (MockedStatic displayMock = mockStatic(Display.class)) {
- Display mockDisplay = mock(Display.class);
- displayMock.when(Display::getDefault).thenReturn(mockDisplay);
- String mockUrl = "127.0.0.1:8000";
- assertEquals(null, ProxyUtil.getHttpsProxyUrl(null, mockUrl));
+ void testDirectProxyReturnsNull() {
+ when(preferenceStore.getString(AmazonQPreferencePage.HTTPS_PROXY)).thenReturn("");
+
+ try (MockedStatic proxyUtilMock = mockStatic(ProxyUtil.class, CALLS_REAL_METHODS)) {
+ proxyUtilMock.when(ProxyUtil::getProxySelector).thenReturn(proxySelector);
+
+ Proxy directProxy = Proxy.NO_PROXY;
+ when(proxySelector.select(any())).thenReturn(Arrays.asList(directProxy));
+
+ assertNull(ProxyUtil.getHttpsProxyUrlForEndpoint("https://foo.com"));
}
}
+ @Test
+ void testPreservesEndpointScheme() {
+ when(preferenceStore.getString(AmazonQPreferencePage.HTTPS_PROXY)).thenReturn("");
+
+ try (MockedStatic proxyUtilMock = mockStatic(ProxyUtil.class, CALLS_REAL_METHODS)) {
+ proxyUtilMock.when(ProxyUtil::getProxySelector).thenReturn(proxySelector);
+
+ Proxy httpProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080));
+ when(proxySelector.select(any())).thenReturn(Arrays.asList(httpProxy));
+
+ assertEquals("http://proxy.example.com:8080", ProxyUtil.getHttpsProxyUrlForEndpoint("http://foo.com"));
+ }
+ }
}
+
diff --git a/pom.xml b/pom.xml
index ad3e8b64a..0190ac67f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,11 +27,7 @@
p2
https://download.eclipse.org/releases/2024-06
-
- lsp4e
- p2
- http://download.eclipse.org/lsp4e/releases/latest/
-
+