Skip to content

[WIP] Add ability to download sources behind authenticated proxy#388

Merged
nbauma109 merged 24 commits into
masterfrom
claude/add-download-sources-behind-proxy
Apr 28, 2026
Merged

[WIP] Add ability to download sources behind authenticated proxy#388
nbauma109 merged 24 commits into
masterfrom
claude/add-download-sources-behind-proxy

Conversation

@Claude
Copy link
Copy Markdown
Contributor

@Claude Claude AI commented Apr 27, 2026

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.


This section details on the original issue you should resolve

<issue_title>Source attach: Download sources behind authenticated system proxy</issue_title>
<issue_description>Currently, in source attach plugin, download behind a proxy is not supported.

Add the ability to download sources behind authenticated system proxy corresponding to Native mode in Eclipse proxy settings.

It must continue to work as before when no proxy is involved (beware possible regressions).</issue_description>

Comments on the Issue (you are @claude[agent] in this section)

- Add org.eclipse.core.net dependency for proxy service
- Create ProxyUtil helper class for proxy configuration
- Update UrlDownloader to use Eclipse proxy settings
- Update AbstractSourceCodeFinder for proxy support
- Update NexusSourceCodeFinder for proxy support
- Update ArtifactorySourceCodeFinder for proxy support
- Update SonatypeSourceCodeFinder for proxy support
- Add basic ProxyUtil tests
- Maintains backward compatibility when no proxy is configured

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/5415a472-2e86-4422-953d-3d9f5857f1d3

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
@nbauma109 nbauma109 marked this pull request as ready for review April 27, 2026 17:29
Copilot AI review requested due to automatic review settings April 27, 2026 17:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds authenticated system proxy support (Eclipse “Native” proxy settings) to the source-attach plugin so that source downloads and repository queries work when running behind an authenticated proxy.

Changes:

  • Introduces a new ProxyUtil helper to obtain a java.net.Proxy from Eclipse IProxyService (with optional proxy authentication setup).
  • Updates URL opening logic in UrlDownloader and multiple SourceCodeFinder implementations to use the Eclipse-selected proxy when available.
  • Adds org.eclipse.core.net to the source-attach bundle dependencies and introduces a basic ProxyUtilTest.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
io.github.nbauma109.decompiler.source.attach/src/io/github/nbauma109/decompiler/source/attach/utils/UrlDownloader.java Uses Eclipse proxy service to open download connections with proxy support
io.github.nbauma109.decompiler.source.attach/src/io/github/nbauma109/decompiler/source/attach/utils/ProxyUtil.java New helper for selecting proxies (and currently sets proxy auth via global Authenticator)
io.github.nbauma109.decompiler.source.attach/src/io/github/nbauma109/decompiler/source/attach/finder/AbstractSourceCodeFinder.java Adds proxy-aware connection opening for getString() and introduces getProxyService()
io.github.nbauma109.decompiler.source.attach/src/io/github/nbauma109/decompiler/source/attach/finder/SonatypeSourceCodeFinder.java Makes Sonatype API POST requests proxy-aware
io.github.nbauma109.decompiler.source.attach/src/io/github/nbauma109/decompiler/source/attach/finder/NexusSourceCodeFinder.java Makes Nexus HTTP requests proxy-aware
io.github.nbauma109.decompiler.source.attach/src/io/github/nbauma109/decompiler/source/attach/finder/ArtifactorySourceCodeFinder.java Makes Artifactory API requests proxy-aware
io.github.nbauma109.decompiler.source.attach/META-INF/MANIFEST.MF Adds dependency on org.eclipse.core.net
io.github.nbauma109.decompiler.source.attach.tests/src/io/github/nbauma109/decompiler/source/attach/utils/ProxyUtilTest.java Adds minimal unit tests for ProxyUtil.getProxy null-service behavior
Comments suppressed due to low confidence (1)

io.github.nbauma109.decompiler.source.attach/src/io/github/nbauma109/decompiler/source/attach/utils/UrlDownloader.java:114

  • UrlDownloader sets a per-connection Authenticator that always returns serviceUser/servicePassword regardless of RequestorType. When running behind an authenticated proxy, this can cause the proxy challenge to receive the repository/service credentials (and may prevent proxy auth from working, since it overrides the proxy Authenticator). Update the Authenticator to only answer for RequestorType.SERVER (or otherwise differentiate proxy vs server auth), and let proxy credentials be handled separately.
            // Set HTTP Basic authentication if credentials are provided
            if (serviceUser != null && servicePassword != null) {
                ((HttpURLConnection) conn).setAuthenticator(new Authenticator() {
                    @Override
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(serviceUser, servicePassword.toCharArray());
                    }
                });

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +41 to +45
public static void configureProxy(URLConnection connection, URI uri, IProxyService proxyService) {
if (proxyService == null) {
return;
}

Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProxyUtil.configureProxy(...) is currently unused, and its connection parameter isn’t used at all. The method also sets global System proxy properties / default Authenticator, which is a JVM-wide side effect and is risky in an Eclipse environment where multiple bundles share the same VM. Consider removing this method for now, or refactoring into a side-effect-free API (e.g., openConnection-with-proxy + per-connection authenticator) that callers actually use.

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +38
@Test
public void getProxyWithNullServiceReturnsNoProxy() throws Exception {
URI uri = new URI("http://example.com");
Proxy proxy = ProxyUtil.getProxy(uri, null);

assertNotNull(proxy);
assertEquals(Proxy.NO_PROXY, proxy);
}

@Test
public void getProxyDoesNotThrowWithValidUri() throws Exception {
// This test verifies that getProxy gracefully handles proxy service errors
URI uri = new URI("http://example.com");

// Should not throw even when proxy service is null
Proxy proxy = ProxyUtil.getProxy(uri, null);
assertNotNull(proxy);
}
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProxyUtilTest currently has two tests that both call getProxy(uri, null) and only assert non-null / NO_PROXY. This doesn’t exercise the new behavior (proxy selection and authenticated proxy handling) and the second test is largely redundant. Consider adding a small stub IProxyService/IProxyData to verify the returned Proxy host/port and (if you keep any Authenticator behavior) that authentication is configured as expected.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +138
private IProxyService getProxyService() {
try {
BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
if (bundleContext != null) {
ServiceReference<IProxyService> serviceReference = bundleContext.getServiceReference(IProxyService.class);
if (serviceReference != null) {
return bundleContext.getService(serviceReference);
}
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getProxyService() calls bundleContext.getService(serviceReference) and returns the service without ever ungetting it. Because this method can be called repeatedly (e.g., each download), it can leak OSGi service usage counts. Consider caching the IProxyService once (e.g., in the plugin activator / a ServiceTracker) and ungetting it on bundle stop, or using a ServiceTracker here instead of repeatedly calling getService().

Copilot uses AI. Check for mistakes.
Comment on lines +107 to +114
protected IProxyService getProxyService() {
try {
BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
if (bundleContext != null) {
ServiceReference<IProxyService> serviceReference = bundleContext.getServiceReference(IProxyService.class);
if (serviceReference != null) {
return bundleContext.getService(serviceReference);
}
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AbstractSourceCodeFinder.getProxyService() returns bundleContext.getService(serviceReference) without ever calling ungetService. Since getString()/open() can be called many times, this can leak OSGi service usage counts. Prefer a ServiceTracker or caching the service once (and ungetting it on bundle stop) rather than acquiring it on every request.

Copilot uses AI. Check for mistakes.
Comment on lines +143 to +147
if (proxyUser != null && !proxyUser.isEmpty() && proxyPassword != null) {
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
if (getRequestorType() == RequestorType.PROXY) {
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProxyUtil.getProxy() installs a JVM-global Authenticator.setDefault(...) as a side effect. This is process-wide state, so concurrent downloads/finders (or other Eclipse plugins) can race/overwrite each other’s proxy credentials, and tests may become order-dependent. Prefer configuring authentication per connection (e.g., HttpURLConnection#setAuthenticator(...) with a RequestorType.PROXY check) or encapsulate proxy opening in a helper that returns an already-configured connection without mutating global state.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a825da0f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

String proxyPassword = proxyData.getPassword();

if (proxyUser != null && !proxyUser.isEmpty() && proxyPassword != null) {
Authenticator.setDefault(new Authenticator() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop setting a JVM-wide authenticator per proxy lookup

ProxyUtil.getProxy calls Authenticator.setDefault(...), which mutates global JVM state every time a request resolves proxy settings. In Eclipse this can interfere with unrelated network traffic (including other plugins) and creates races when concurrent downloads need different proxy credentials, because the last caller wins. This should avoid process-wide mutation and keep authentication scoped to the specific connection/request.

Useful? React with 👍 / 👎.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

❌ Patch coverage is 78.02198% with 80 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.81%. Comparing base (45c90ef) to head (9fada6c).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
.../decompiler/source/attach/testutil/ProxyStubs.java 36.84% 24 Missing ⚠️
.../decompiler/source/attach/utils/UrlDownloader.java 50.00% 6 Missing and 8 partials ⚠️
...source/attach/finder/AbstractSourceCodeFinder.java 64.00% 8 Missing and 1 partial ⚠️
...ompiler/source/attach/utils/UrlDownloaderTest.java 87.69% 5 Missing and 3 partials ⚠️
...a109/decompiler/source/attach/utils/ProxyUtil.java 65.00% 4 Missing and 3 partials ⚠️
...rce/attach/finder/ArtifactorySourceCodeFinder.java 62.50% 2 Missing and 1 partial ⚠️
...er/source/attach/finder/NexusSourceCodeFinder.java 62.50% 2 Missing and 1 partial ⚠️
...source/attach/finder/SonatypeSourceCodeFinder.java 62.50% 2 Missing and 1 partial ⚠️
...9/decompiler/source/attach/SourceAttachPlugin.java 71.42% 0 Missing and 2 partials ⚠️
...iler/editor/JavaDecompilerClassFileEditorTest.java 60.00% 2 Missing ⚠️
... and 5 more
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #388      +/-   ##
============================================
+ Coverage     58.28%   58.81%   +0.52%     
- Complexity      437      460      +23     
============================================
  Files           123      127       +4     
  Lines          8036     8313     +277     
  Branches       1089     1118      +29     
============================================
+ Hits           4684     4889     +205     
- Misses         2724     2778      +54     
- Partials        628      646      +18     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/02affcbc-f1a7-4440-82a4-fb4186c10018

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
Copilot AI and others added 2 commits April 28, 2026 10:40
…ed ProxyStubs utility

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/815c940a-1134-480d-b933-12310a1f0d65

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
…ception types)

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/2fa88b59-f82f-4d2c-8287-598932ecf8ce

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
…/test-classes/

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/f49fb645-a23e-4f8a-b469-d380b2ff8fd2

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
…sertion-in-production-code warnings

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/7c27630c-f476-48bb-9976-7c9260015d71

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
Copilot AI and others added 2 commits April 28, 2026 15:09
- Add awaitCompletion() to FinderManager to enable join-based waiting
- FinderManagerTest: use awaitCompletion() instead of Thread.sleep polling loop, add assertion to cancelAfterFindSourcesWithEmptyListDoesNotThrow
- GAVTest: replace assertFalse(equals) with assertNotEquals
- Create MavenRepoSourceCodeFinderNullCoordinateTest with @parameterized replacing 3 duplicate tests; remove those from MavenRepoSourceCodeFinderTest
- SourceCodeFinderFacadeTest: add assertNull assertion to cancelDoesNotThrow
- AttachSourceActionTest: replace Thread.sleep with LockSupport.parkNanos in waitForSourceAttachment
- JavaSourceAttacherHandlerTest: assertEquals for path check, LockSupport.parkNanos for sleep
- SourceBindingUtilTest: add assertNull assertions to 4 no-op tests
- SourceConstantsTest: swap assertEquals arguments to expected, actual order
- UrlDownloaderTest: refactor try/catch to @test(expected=UnsupportedOperationException.class)
- ExportSourceActionTest: refactor try/catch to @test(expected=IOException.class)
- EditorUtilityTest: add assertNotNull assertion to startupEarlyStartupIsNoOp
- JavaDecompilerClassFileEditorTest: assertSame instead of assertTrue(==), LockSupport.parkNanos for sleeps
- DecompileUtilPluginTest: assertEquals(Boolean.TRUE, ...) instead of assertTrue(equals)
- LoggerTest: add assertNoException helper and use it in all 7 test methods

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/d9d5b95c-5085-4876-90ea-204d2512bfda

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
…param in tests

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/9eef8519-2d8b-400a-abe6-24a1cf631144

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
…vaDecompilerClassFileEditorTest

Agent-Logs-Url: https://github.com/nbauma109/ecd/sessions/23d4f5da-3ed0-47f6-9457-115bbd24cf65

Co-authored-by: nbauma109 <9403560+nbauma109@users.noreply.github.com>
@sonarqubecloud
Copy link
Copy Markdown

@nbauma109 nbauma109 merged commit c7948fe into master Apr 28, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Source attach: Download sources behind authenticated system proxy

5 participants