Skip to content

Commit 82f9917

Browse files
committed
Remove signatures from wrapped source bundles
Currently when the source bundle is signed, wrapping it into a source bundle will break the signature and make the jar invalid. This now removes the signature from source bundles as they are transformed.
1 parent c464287 commit 82f9917

File tree

5 files changed

+112
-48
lines changed

5 files changed

+112
-48
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
import java.util.function.Function;
3333
import java.util.function.Predicate;
3434
import java.util.jar.Attributes;
35+
import java.util.jar.JarEntry;
3536
import java.util.jar.JarFile;
37+
import java.util.jar.JarInputStream;
3638
import java.util.stream.Collectors;
3739

3840
import org.eclipse.core.runtime.IStatus;
@@ -163,6 +165,17 @@ static Attributes getManifestMainAttributes(TargetBundle targetBundle) throws IO
163165
}
164166
}
165167

168+
static void assertValidSignature(TargetBundle targetBundle) throws IOException {
169+
try (JarInputStream stream = new JarInputStream(
170+
targetBundle.getBundleInfo().getLocation().toURL().openStream())) {
171+
for (JarEntry entry = stream.getNextJarEntry(); entry != null; entry = stream.getNextJarEntry()) {
172+
for (byte[] drain = new byte[4096]; stream.read(drain, 0, drain.length) != -1;) {
173+
// nothing we just want to trigger the signature verification
174+
}
175+
}
176+
}
177+
}
178+
166179
static void assertTargetBundles(ITargetLocation target, List<ExpectedBundle> expectedUnits) {
167180
assertTargetContent(expectedUnits, target.getBundles(), //
168181
(expectedBundle, bundle) -> {

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,39 @@ public void testBadSymbolicName() throws Exception {
7171
assertStatusOk(getTargetStatus(target));
7272
}
7373

74+
@Test
75+
public void testSourceWithSignature() throws Exception {
76+
ITargetLocation target = resolveMavenTarget(
77+
"""
78+
<location includeDependencyDepth="none" includeDependencyScopes="compile" label="LemMinX" includeSource="true" missingManifest="error" type="Maven">
79+
<dependencies>
80+
<dependency>
81+
<groupId>org.eclipse.lemminx</groupId>
82+
<artifactId>org.eclipse.lemminx</artifactId>
83+
<version>0.29.0</version>
84+
<type>jar</type>
85+
</dependency>
86+
</dependencies>
87+
<repositories>
88+
<repository>
89+
<id>lemminx-releases</id>
90+
<url>https://repo.eclipse.org/content/repositories/lemminx-releases/</url>
91+
</repository>
92+
</repositories>
93+
</location>
94+
""");
95+
assertStatusOk(getTargetStatus(target));
96+
TargetBundle[] allBundles = target.getBundles();
97+
boolean sourcesFound = false;
98+
for (TargetBundle targetBundle : allBundles) {
99+
if (targetBundle.isSourceBundle()) {
100+
sourcesFound = true;
101+
assertValidSignature(targetBundle);
102+
}
103+
}
104+
assertTrue("No source bundle generated!", sourcesFound);
105+
}
106+
74107
@Test
75108
public void testBadDependencyDirect() throws Exception {
76109
ITargetLocation target = resolveMavenTarget("""

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

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -13,80 +13,41 @@
1313
package org.eclipse.m2e.pde.target;
1414

1515
import java.io.File;
16-
import java.io.FileInputStream;
17-
import java.io.FileOutputStream;
18-
import java.io.IOException;
1916
import java.util.Objects;
20-
import java.util.jar.Attributes;
21-
import java.util.jar.Attributes.Name;
22-
import java.util.jar.JarEntry;
2317
import java.util.jar.JarFile;
24-
import java.util.jar.JarInputStream;
25-
import java.util.jar.JarOutputStream;
2618
import java.util.jar.Manifest;
27-
import java.util.zip.ZipEntry;
2819

2920
import org.eclipse.aether.artifact.Artifact;
3021
import org.eclipse.equinox.frameworkadmin.BundleInfo;
22+
import org.eclipse.m2e.pde.target.shared.MavenBundleWrapper;
3123
import org.eclipse.pde.core.target.TargetBundle;
32-
import org.osgi.framework.Constants;
3324

3425
public class MavenSourceBundle extends TargetBundle {
3526

36-
@SuppressWarnings("restriction")
37-
public static final String ECLIPSE_SOURCE_BUNDLE_HEADER = org.eclipse.pde.internal.core.ICoreConstants.ECLIPSE_SOURCE_BUNDLE;
38-
3927
public MavenSourceBundle(BundleInfo sourceTarget, Artifact artifact, CacheManager cacheManager) throws Exception {
4028
this.fSourceTarget = sourceTarget;
41-
fInfo.setSymbolicName(sourceTarget.getSymbolicName() + ".source");
42-
fInfo.setVersion(sourceTarget.getVersion());
29+
String symbolicName = sourceTarget.getSymbolicName();
30+
String version = sourceTarget.getVersion();
31+
fInfo.setSymbolicName(MavenBundleWrapper.getSourceBundleName(symbolicName));
32+
fInfo.setVersion(version);
4333
Manifest manifest;
4434
File sourceFile = artifact.getFile();
4535
try (JarFile jar = new JarFile(sourceFile)) {
4636
manifest = Objects.requireNonNullElseGet(jar.getManifest(), Manifest::new);
4737
}
48-
if (isValidSourceManifest(manifest)) {
38+
if (MavenBundleWrapper.isValidSourceManifest(manifest)) {
4939
fInfo.setLocation(sourceFile.toURI());
5040
} else {
5141
File generatedSourceBundle = cacheManager.accessArtifactFile(artifact, file -> {
5242
if (CacheManager.isOutdated(file, sourceFile)) {
53-
addSourceBundleMetadata(manifest, sourceTarget);
54-
transferJarEntries(sourceFile, manifest, file);
43+
MavenBundleWrapper.addSourceBundleMetadata(manifest, symbolicName, version);
44+
MavenBundleWrapper.transferJarEntries(sourceFile, manifest, file);
5545
}
5646
return file;
5747
});
5848
fInfo.setLocation(generatedSourceBundle.toURI());
5949
}
6050
}
6151

62-
private void addSourceBundleMetadata(Manifest manifest, BundleInfo bundle) {
63-
Attributes attr = manifest.getMainAttributes();
64-
if (attr.isEmpty()) {
65-
attr.put(Name.MANIFEST_VERSION, "1.0");
66-
}
67-
attr.putValue(ECLIPSE_SOURCE_BUNDLE_HEADER,
68-
bundle.getSymbolicName() + ";version=\"" + bundle.getVersion() + "\";roots:=\".\"");
69-
attr.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
70-
attr.putValue(Constants.BUNDLE_NAME,
71-
"Source Bundle for " + bundle.getSymbolicName() + ":" + bundle.getVersion());
72-
attr.putValue(Constants.BUNDLE_SYMBOLICNAME, fInfo.getSymbolicName());
73-
attr.putValue(Constants.BUNDLE_VERSION, fInfo.getVersion());
74-
}
75-
76-
private void transferJarEntries(File source, Manifest manifest, File target) throws IOException {
77-
try (var output = new JarOutputStream(new FileOutputStream(target), manifest);
78-
var input = new JarInputStream(new FileInputStream(source));) {
79-
for (JarEntry entry; (entry = input.getNextJarEntry()) != null;) {
80-
if (!JarFile.MANIFEST_NAME.equals(entry.getName())) {
81-
output.putNextEntry(new ZipEntry(entry.getName()));
82-
input.transferTo(output);
83-
}
84-
}
85-
}
86-
}
87-
88-
private static boolean isValidSourceManifest(Manifest manifest) {
89-
return manifest != null && manifest.getMainAttributes().getValue(ECLIPSE_SOURCE_BUNDLE_HEADER) != null;
90-
}
9152

9253
}

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
package org.eclipse.m2e.pde.target.shared;
1414

1515
import java.io.File;
16+
import java.io.FileInputStream;
17+
import java.io.FileOutputStream;
1618
import java.io.IOException;
1719
import java.nio.file.Files;
1820
import java.nio.file.Path;
@@ -27,10 +29,16 @@
2729
import java.util.Set;
2830
import java.util.function.Function;
2931
import java.util.jar.Attributes;
32+
import java.util.jar.Attributes.Name;
33+
import java.util.jar.JarEntry;
34+
import java.util.jar.JarFile;
35+
import java.util.jar.JarInputStream;
36+
import java.util.jar.JarOutputStream;
3037
import java.util.jar.Manifest;
3138
import java.util.regex.Pattern;
3239
import java.util.stream.Collectors;
3340
import java.util.stream.Stream;
41+
import java.util.zip.ZipEntry;
3442

3543
import org.apache.commons.codec.digest.DigestUtils;
3644
import org.apache.maven.model.Model;
@@ -71,6 +79,10 @@
7179
* </ul>
7280
*/
7381
public class MavenBundleWrapper {
82+
83+
@SuppressWarnings("restriction")
84+
public static final String ECLIPSE_SOURCE_BUNDLE_HEADER = org.eclipse.pde.internal.core.ICoreConstants.ECLIPSE_SOURCE_BUNDLE;
85+
7486
private MavenBundleWrapper() {
7587
}
7688

@@ -308,4 +320,49 @@ public static boolean isOutdated(Path cacheFile, Path sourceFile) throws IOExcep
308320
}
309321
return true;
310322
}
323+
324+
private static boolean isExcludedFromWrapping(String name) {
325+
return name.equals(JarFile.MANIFEST_NAME) || name.startsWith("META-INF/SIG-") || name.startsWith("META-INF/")
326+
&& (name.endsWith(".SF") || name.endsWith(".RSA") || name.endsWith(".DSA"));
327+
}
328+
329+
public static void addSourceBundleMetadata(Manifest manifest, String symbolicName, String version) {
330+
331+
Attributes attr = manifest.getMainAttributes();
332+
if (attr.isEmpty()) {
333+
attr.put(Name.MANIFEST_VERSION, "1.0");
334+
}
335+
attr.putValue(ECLIPSE_SOURCE_BUNDLE_HEADER, symbolicName + ";version=\"" + version + "\";roots:=\".\"");
336+
attr.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
337+
attr.putValue(Constants.BUNDLE_NAME, "Source Bundle for " + symbolicName + ":" + version);
338+
attr.putValue(Constants.BUNDLE_SYMBOLICNAME, getSourceBundleName(symbolicName));
339+
attr.putValue(Constants.BUNDLE_VERSION, version);
340+
}
341+
342+
public static String getSourceBundleName(String symbolicName) {
343+
return symbolicName + ".source";
344+
}
345+
346+
public static void transferJarEntries(File source, Manifest manifest, File target) throws IOException {
347+
Map<String, Attributes> manifestEntries = manifest.getEntries();
348+
if (manifestEntries != null) {
349+
// need to clear out signature infos
350+
manifestEntries.clear();
351+
}
352+
try (var output = new JarOutputStream(new FileOutputStream(target), manifest);
353+
var input = new JarInputStream(new FileInputStream(source));) {
354+
for (JarEntry entry; (entry = input.getNextJarEntry()) != null;) {
355+
if (MavenBundleWrapper.isExcludedFromWrapping(entry.getName())) {
356+
// Exclude manifest and signatures
357+
continue;
358+
}
359+
output.putNextEntry(new ZipEntry(entry.getName()));
360+
input.transferTo(output);
361+
}
362+
}
363+
}
364+
365+
public static boolean isValidSourceManifest(Manifest manifest) {
366+
return manifest != null && manifest.getMainAttributes().getValue(ECLIPSE_SOURCE_BUNDLE_HEADER) != null;
367+
}
311368
}

target-platform/target-platform.target

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
</dependency>
117117
</dependencies>
118118
</location>
119-
<location includeDependencyDepth="none" includeDependencyScopes="compile" label="LemMinX" includeSource="true" missingManifest="error" type="Maven">
119+
<location includeDependencyDepth="none" includeDependencyScopes="compile" label="LemMinX" includeSource="false" missingManifest="error" type="Maven">
120120
<dependencies>
121121
<dependency>
122122
<groupId>org.eclipse.lemminx</groupId>

0 commit comments

Comments
 (0)