Skip to content

Commit 4ae13c2

Browse files
committed
Add tracing to maven protocol handler and force update for snapshots
Currently if something goes wrong with the maven protocol handler it is very hard to get a sense of what's going on. This now enables tracing for m2e and using that in the protocol handler to allow further analysis in case where things go wrong.
1 parent 787b86f commit 4ae13c2

File tree

6 files changed

+95
-16
lines changed

6 files changed

+95
-16
lines changed

org.eclipse.m2e.core.ui/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ Require-Bundle: org.eclipse.m2e.core;bundle-version="[2.0.0,3.0.0)",
4242
org.eclipse.core.filebuffers,
4343
org.eclipse.ui,
4444
org.eclipse.ui.navigator,
45-
org.eclipse.debug.ui
45+
org.eclipse.debug.ui,
46+
org.eclipse.ui.trace
4647
Import-Package: org.apache.maven.archetype.catalog;provider=m2e;version="[3.2.1,4.0.0)",
4748
org.apache.maven.archetype.catalog.io.xpp3;provider=m2e;version="[3.2.1,4.0.0)",
4849
org.apache.maven.archetype.common;provider=m2e;version="[3.2.1,4.0.0)",

org.eclipse.m2e.core.ui/plugin.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,4 +746,15 @@
746746
</enablement>
747747
</commonWizard>
748748
</extension>
749+
<extension
750+
point="org.eclipse.ui.trace.traceComponents">
751+
<component
752+
id="org.eclipse.m2e.core.ui.component1"
753+
label="M2E Maven Integration for Eclipse">
754+
<bundle
755+
consumed="true"
756+
name="org.eclipse.m2e.*">
757+
</bundle>
758+
</component>
759+
</extension>
749760
</plugin>

org.eclipse.m2e.core/.options

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.eclipse.m2e.core/mvnProtocolHandler=false

org.eclipse.m2e.core/.settings/org.eclipse.pde.ds.annotations.prefs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
classpath=true
2-
dsVersion=V1_3
2+
dsVersion=V1_5
33
eclipse.preferences.version=1
44
enabled=true
55
generateBundleActivationPolicyLazy=true

org.eclipse.m2e.core/build.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ bin.includes = plugin.xml,\
2020
m2eclipse.gif,\
2121
about_files/,\
2222
OSGI-INF/,\
23-
lifecycle-mapping-metadata.xml
23+
lifecycle-mapping-metadata.xml,\
24+
.options
2425
output.. = bin/
2526
source.. = src/,\
2627
src-gen/

org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MvnProtocolHandlerService.java

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2020 Christoph Läubrich and others.
2+
* Copyright (c) 2020, 2025 Christoph Läubrich and others.
33
* This program and the accompanying materials
44
* are made available under the terms of the Eclipse Public License 2.0
55
* which accompanies this distribution, and is available at
@@ -18,11 +18,19 @@
1818
import java.io.FileNotFoundException;
1919
import java.io.IOException;
2020
import java.io.InputStream;
21+
import java.net.URI;
22+
import java.net.URISyntaxException;
2123
import java.net.URL;
2224
import java.net.URLConnection;
25+
import java.util.Hashtable;
2326
import java.util.List;
27+
import java.util.stream.Collectors;
2428

29+
import org.osgi.framework.BundleContext;
30+
import org.osgi.framework.ServiceRegistration;
31+
import org.osgi.service.component.annotations.Activate;
2532
import org.osgi.service.component.annotations.Component;
33+
import org.osgi.service.component.annotations.Deactivate;
2634
import org.osgi.service.component.annotations.Reference;
2735
import org.osgi.service.url.AbstractURLStreamHandlerService;
2836
import org.osgi.service.url.URLConstants;
@@ -40,6 +48,9 @@
4048
import org.eclipse.core.runtime.IProgressMonitor;
4149
import org.eclipse.core.runtime.NullProgressMonitor;
4250
import org.eclipse.core.runtime.Status;
51+
import org.eclipse.osgi.service.debug.DebugOptions;
52+
import org.eclipse.osgi.service.debug.DebugOptionsListener;
53+
import org.eclipse.osgi.service.debug.DebugTrace;
4354

4455
import org.apache.maven.RepositoryUtils;
4556
import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -50,18 +61,43 @@
5061

5162

5263
@Component(service = URLStreamHandlerService.class, property = URLConstants.URL_HANDLER_PROTOCOL + "=mvn")
53-
public class MvnProtocolHandlerService extends AbstractURLStreamHandlerService {
64+
public class MvnProtocolHandlerService extends AbstractURLStreamHandlerService implements DebugOptionsListener {
5465

55-
@Reference
56-
IMaven maven;
66+
private static final String ID = "org.eclipse.m2e.core";
67+
68+
private static final String OPTION = "/mvnProtocolHandler";
69+
70+
private final IMaven maven;
71+
72+
private volatile DebugTrace debugTrace;
73+
74+
private final ServiceRegistration<DebugOptionsListener> serviceRegistration;
75+
76+
@Activate
77+
public MvnProtocolHandlerService(@Reference IMaven maven, BundleContext bundleContext) {
78+
this.maven = maven;
79+
//We need to register this manually here to we are lazy as otherwise it would activate this component immediately
80+
Hashtable<String, Object> hashtable = new Hashtable<>();
81+
hashtable.put(DebugOptions.LISTENER_SYMBOLICNAME, ID);
82+
serviceRegistration = bundleContext.registerService(DebugOptionsListener.class, this, hashtable);
83+
}
84+
85+
@Deactivate
86+
void shutdown() {
87+
serviceRegistration.unregister();
88+
}
89+
@Override
90+
public void optionsChanged(DebugOptions options) {
91+
if(options.getBooleanOption(ID + OPTION, false)) {
92+
this.debugTrace = options.newDebugTrace(ID, MvnProtocolHandlerService.class);
93+
} else {
94+
this.debugTrace = null;
95+
}
96+
}
5797

5898
@Override
5999
public URLConnection openConnection(URL url) {
60-
//TODO replace reference with IMaven maven = MavenPlugin.getMaven();
61-
//this is required to make the component active even if m2e itself is not running at the moment
62-
//that will make the m2e protocol available from the start of eclipse
63-
//See https://github.com/eclipse-equinox/equinox/pull/290
64-
return new MavenURLConnection(url, maven);
100+
return new MavenURLConnection(url, maven, debugTrace);
65101
}
66102

67103
private static final class MavenURLConnection extends URLConnection {
@@ -70,11 +106,14 @@ private static final class MavenURLConnection extends URLConnection {
70106

71107
private ArtifactResult artifactResult;
72108

73-
private IMaven maven;
109+
private final IMaven maven;
110+
111+
private final DebugTrace debugTrace;
74112

75-
protected MavenURLConnection(URL url, IMaven maven) {
113+
protected MavenURLConnection(URL url, IMaven maven, DebugTrace debugTrace) {
76114
super(url);
77115
this.maven = maven;
116+
this.debugTrace = debugTrace;
78117
}
79118

80119
@Override
@@ -86,6 +125,9 @@ public void connect() throws IOException {
86125
if(path == null) {
87126
throw new IOException("maven coordinates are missing");
88127
}
128+
if(debugTrace != null) {
129+
debugTrace.trace(OPTION, "connect to " + url);
130+
}
89131
int subPathIndex = path.indexOf('/');
90132

91133
String[] coordinates;
@@ -104,8 +146,18 @@ public void connect() throws IOException {
104146
try {
105147
RepositorySystem repoSystem = maven.lookup(RepositorySystem.class);
106148
IMavenExecutionContext context = maven.createExecutionContext();
149+
boolean isSnapshot = artifact.getBaseVersion().endsWith("-SNAPSHOT");
150+
if(isSnapshot && !context.getExecutionRequest().isUpdateSnapshots()) {
151+
//if a snapshot version is requested, always force an update!
152+
context.getExecutionRequest().setUpdateSnapshots(true);
153+
}
107154
List<ArtifactRepository> artifactRepositories = maven.getArtifactRepositories();
108155
List<RemoteRepository> remoteRepositories = RepositoryUtils.toRepos(artifactRepositories);
156+
if(debugTrace != null) {
157+
debugTrace.trace(OPTION, "Fetching artifact " + artifact + " using "
158+
+ remoteRepositories.stream().map(rp -> rp.getUrl()).collect(Collectors.joining(", "))
159+
+ " with update snapshots = " + context.getExecutionRequest().isUpdateSnapshots());
160+
}
109161
artifactResult = context.execute(new ICallable<ArtifactResult>() {
110162

111163
@Override
@@ -115,6 +167,9 @@ public ArtifactResult call(IMavenExecutionContext context, IProgressMonitor moni
115167
try {
116168
return repoSystem.resolveArtifact(session, artifactRequest);
117169
} catch(ArtifactResolutionException e) {
170+
if(debugTrace != null) {
171+
debugTrace.trace(OPTION, "resolving of artifact " + artifact + " failed!", e);
172+
}
118173
throw new CoreException(Status.error("Resolving artifact failed", e));
119174
}
120175
}
@@ -132,17 +187,27 @@ public InputStream getInputStream() throws IOException {
132187
}
133188
File location = artifactResult.getArtifact().getFile();
134189
if(subPath == null) {
190+
if(debugTrace != null) {
191+
debugTrace.trace(OPTION, "Open stream to artifact file " + location);
192+
}
135193
return new FileInputStream(location);
136194
}
137195
String urlSpec = "jar:" + location.toURI() + "!" + subPath;
138-
return new URL(urlSpec).openStream();
196+
try {
197+
if(debugTrace != null) {
198+
debugTrace.trace(OPTION, "Open stream to subpath in artifact file " + urlSpec);
199+
}
200+
return new URI(urlSpec).toURL().openStream();
201+
} catch(URISyntaxException ex) {
202+
throw new IOException(ex);
203+
}
139204
}
140205

141206
@Override
142207
public long getLastModified() {
143208
try {
144209
connect();
145-
} catch (IOException e) {
210+
} catch(IOException e) {
146211
return 0;
147212
}
148213
if(artifactResult == null || artifactResult.isMissing()) {

0 commit comments

Comments
 (0)