Skip to content

Commit c4163ad

Browse files
committed
Do not fail if wrapping dependencies fails
Fix #1402
1 parent 3ed03c8 commit c4163ad

File tree

4 files changed

+132
-14
lines changed

4 files changed

+132
-14
lines changed

org.eclipse.m2e.pde.target.tests/src/org/eclipse/m2e/pde/target/tests/OSGiMetadataGenerationTest.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,58 @@
3939
public class OSGiMetadataGenerationTest extends AbstractMavenTargetTest {
4040

4141
@Test
42-
// @Ignore("currently fails on CI")
42+
public void testBadDependencyInChain() throws Exception {
43+
ITargetLocation target = resolveMavenTarget("""
44+
<location includeDependencyScope="compile" missingManifest="generate" type="Maven">
45+
<dependencies>
46+
<dependency>
47+
<groupId>edu.ucar</groupId>
48+
<artifactId>cdm</artifactId>
49+
<version>4.5.5</version>
50+
<type>jar</type>
51+
</dependency>
52+
</dependencies>
53+
</location>
54+
""");
55+
assertStatusOk(getTargetStatus(target));
56+
}
57+
58+
@Test
59+
public void testBadDependencyDirect() throws Exception {
60+
ITargetLocation target = resolveMavenTarget("""
61+
<location missingManifest="generate" type="Maven">
62+
<dependencies>
63+
<dependency>
64+
<groupId>com.ibm.icu</groupId>
65+
<artifactId>icu4j</artifactId>
66+
<version>2.6.1</version>
67+
<type>jar</type>
68+
</dependency>
69+
</dependencies>
70+
</location>
71+
""");
72+
IStatus targetStatus = getTargetStatus(target);
73+
assertEquals(String.valueOf(targetStatus), IStatus.ERROR, targetStatus.getSeverity());
74+
}
75+
76+
@Test
77+
public void testMissingOptionalDependency() throws Exception {
78+
ITargetLocation target = resolveMavenTarget("""
79+
<location includeDependencyDepth="none" includeDependencyScopes="compile" missingManifest="generate" type="Maven">
80+
<dependencies>
81+
<dependency>
82+
<groupId>net.sf.saxon</groupId>
83+
<artifactId>Saxon-HE</artifactId>
84+
<version>10.9</version>
85+
<type>jar</type>
86+
</dependency>
87+
</dependencies>
88+
</location>
89+
""");
90+
assertStatusOk(getTargetStatus(target));
91+
}
92+
93+
@Test
4394
public void testNonOSGiArtifact_missingArtifactError() throws Exception {
4495
ITargetLocation target = resolveMavenTarget("""
4596
<location includeDependencyDepth="none" includeSource="true" missingManifest="error" type="Maven">

org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/MavenTargetBundle.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,24 +132,29 @@ private static TargetBundle getWrappedArtifact(Artifact artifact, MavenTargetLoc
132132
};
133133
IMavenExecutionContext exeContext = IMavenExecutionContext.getThreadContext()
134134
.orElseGet(maven::createExecutionContext);
135-
135+
MultiStatus bundleStatus = new MultiStatus(MavenTargetBundle.class, 0,
136+
"Some problems where detected while wrapping " + artifact);
136137
Path wrappedBundle = exeContext.execute((context, monitor1) -> {
137138
RepositorySystem repoSystem = MavenPluginActivator.getDefault().getRepositorySystem();
138139
RepositorySystemSession repositorySession = context.getRepositorySession();
139140
try {
140141
WrappedBundle wrap = MavenBundleWrapper.getWrappedArtifact(artifact, instructionsLookup, repositories,
141142
repoSystem, repositorySession, context.getComponentLookup().lookup(SyncContextFactory.class));
142-
List<ProcessingMessage> errors = wrap.messages()
143+
List<ProcessingMessage> directErrors = wrap.messages(false)
143144
.filter(msg -> msg.type() == ProcessingMessage.Type.ERROR).toList();
144-
if (errors.isEmpty()) {
145+
if (directErrors.isEmpty()) {
146+
// treat all items as warnings....
147+
wrap.messages(true).map(ProcessingMessage::message).distinct().forEach(msg -> {
148+
bundleStatus.add(Status.warning(msg));
149+
});
145150
return wrap.getFile();
146151
}
147-
if (errors.size() == 1) {
148-
throw new CoreException(Status.error(errors.get(0).message()));
152+
if (directErrors.size() == 1) {
153+
throw new CoreException(Status.error(directErrors.get(0).message()));
149154
}
150155
MultiStatus multiStatus = new MultiStatus(MavenTargetBundle.class, IStatus.ERROR,
151156
"wrapping artifact " + artifact.getArtifactId() + " failed!");
152-
for (ProcessingMessage message : errors) {
157+
for (ProcessingMessage message : directErrors) {
153158
multiStatus.add(Status.error(message.message()));
154159
}
155160
throw new CoreException(multiStatus);
@@ -159,7 +164,17 @@ private static TargetBundle getWrappedArtifact(Artifact artifact, MavenTargetLoc
159164
throw new CoreException(Status.error("Can't collect dependencies!", e));
160165
}
161166
}, monitor);
162-
return new TargetBundle(wrappedBundle.toFile());
167+
TargetBundle bundle = new TargetBundle(wrappedBundle.toFile()) {
168+
@Override
169+
public IStatus getStatus() {
170+
if (!bundleStatus.isOK()) {
171+
// TODO see https://github.com/eclipse-pde/eclipse.pde/issues/656
172+
// return bundleStatus;
173+
}
174+
return super.getStatus();
175+
}
176+
};
177+
return bundle;
163178

164179
}
165180

org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/MavenBundleWrapper.java

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@
3939
import org.eclipse.aether.artifact.Artifact;
4040
import org.eclipse.aether.collection.CollectRequest;
4141
import org.eclipse.aether.graph.Dependency;
42+
import org.eclipse.aether.graph.DependencyFilter;
4243
import org.eclipse.aether.graph.DependencyNode;
4344
import org.eclipse.aether.graph.DependencyVisitor;
4445
import org.eclipse.aether.impl.SyncContextFactory;
4546
import org.eclipse.aether.repository.RemoteRepository;
47+
import org.eclipse.aether.resolution.ArtifactRequest;
48+
import org.eclipse.aether.resolution.ArtifactResolutionException;
4649
import org.eclipse.aether.resolution.DependencyRequest;
50+
import org.eclipse.aether.resolution.DependencyResolutionException;
4751
import org.eclipse.core.runtime.Platform;
4852
import org.eclipse.m2e.pde.target.shared.ProcessingMessage.Type;
4953
import org.osgi.framework.Constants;
@@ -96,6 +100,22 @@ public static WrappedBundle getWrappedArtifact(Artifact artifact,
96100

97101
DependencyRequest dependencyRequest = new DependencyRequest();
98102
dependencyRequest.setRoot(node);
103+
dependencyRequest.setFilter(new DependencyFilter() {
104+
105+
@Override
106+
public boolean accept(DependencyNode node, List<DependencyNode> parents) {
107+
ArtifactRequest request = new ArtifactRequest();
108+
request.setRepositories(repositories);
109+
Artifact nodeArtifact = node.getArtifact();
110+
request.setArtifact(nodeArtifact);
111+
try {
112+
repoSystem.resolveArtifact(repositorySession, request);
113+
} catch (ArtifactResolutionException e) {
114+
return false;
115+
}
116+
return true;
117+
}
118+
});
99119
repoSystem.resolveDependencies(repositorySession, dependencyRequest);
100120

101121
try (SyncContext syncContext = syncContextFactory.newInstance(repositorySession, false)) {
@@ -117,7 +137,10 @@ public boolean visitEnter(DependencyNode n) {
117137
Map<DependencyNode, WrappedBundle> visited = new HashMap<>();
118138
WrappedBundle wrappedNode = getWrappedNode(node, instructionsLookup, visited);
119139
for (WrappedBundle wrap : visited.values()) {
120-
wrap.getJar().close();
140+
Jar jar = wrap.getJar();
141+
if (jar != null) {
142+
jar.close();
143+
}
121144
}
122145
return wrappedNode;
123146
}
@@ -132,6 +155,18 @@ private static WrappedBundle getWrappedNode(DependencyNode node,
132155
}
133156
Artifact artifact = node.getArtifact();
134157
File originalFile = artifact.getFile();
158+
if (originalFile == null) {
159+
if (node.getDependency().isOptional()) {
160+
visited.put(node,
161+
wrappedNode = new WrappedBundle(node, List.of(), null, null, null,
162+
List.of(new ProcessingMessage(artifact, Type.WARN,
163+
"Optional artifact " + node.getArtifact() + " was not found"))));
164+
} else {
165+
visited.put(node, wrappedNode = new WrappedBundle(node, List.of(), null, null, null, List.of(
166+
new ProcessingMessage(artifact, Type.ERROR, "Artifact " + node.getArtifact() + " not found"))));
167+
}
168+
return wrappedNode;
169+
}
135170
Jar jar = new Jar(originalFile);
136171
Manifest originalManifest = jar.getManifest();
137172
if (originalManifest != null
@@ -174,8 +209,14 @@ private static WrappedBundle getWrappedNode(DependencyNode node,
174209
analyzer.setProperty(property, trimValue);
175210
}
176211
for (WrappedBundle dep : depends) {
177-
analyzer.addClasspath(dep.getJar());
178-
analyzer.removeClose(dep.getJar());
212+
Jar depJar = dep.getJar();
213+
if (depJar == null) {
214+
messages.add(new ProcessingMessage(artifact, Type.WARN,
215+
"Dependency " + dep.getNode().getDependency() + " was ignored!"));
216+
continue;
217+
}
218+
analyzer.addClasspath(depJar);
219+
analyzer.removeClose(depJar);
179220
}
180221
analyzerJar.setManifest(analyzer.calcManifest());
181222
analyzerJar.write(wrapArtifactFile);

org.eclipse.m2e.pde.target/src/org/eclipse/m2e/pde/target/shared/WrappedBundle.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,25 @@ Jar getJar() {
4848
return jar;
4949
}
5050

51+
DependencyNode getNode() {
52+
return node;
53+
}
54+
5155
/** @return the location of the wrapped bundle's files */
5256
public Path getFile() {
5357
return file;
5458
}
5559

56-
/** @return the messages that where produced */
57-
public Stream<ProcessingMessage> messages() {
58-
return Stream.concat(messages.stream(), depends.stream().flatMap(dep -> dep.messages()));
60+
/**
61+
* @param includeDependent if <code>true</code> includes messages from dependent
62+
* items.
63+
* @return the messages that where produced
64+
*/
65+
public Stream<ProcessingMessage> messages(boolean includeDependent) {
66+
if (includeDependent) {
67+
return Stream.concat(messages.stream(), depends.stream().flatMap(dep -> dep.messages(true)));
68+
}
69+
return messages.stream();
5970
}
6071

6172
@Override

0 commit comments

Comments
 (0)