Skip to content

Commit

Permalink
Extract referenced slf4j bundle for Maven runtime classpath again
Browse files Browse the repository at this point in the history
This is necessary because even the slf4j-bundle from Maven-Central is
jar-singed as part of the m2e build when the m2e-repo is assembled.

If the slf4j-jar is not extracted launching the embedded maven-runtime
will fail with errors like:
```
class "org.slf4j.MavenSlf4jFriend"'s signer information does not match
signer information of other classes in the same package
```
The reason for such an error is that the 'slf4j-api' jar and the
'maven-slf4j-provider' jar both provide classes for the package
'org.slf4j'. But all jars that provide classes for the same package must
have the same jar-signer. And while the 'slf4j-api' jar is referenced as
bundle and therefore signed in the m2e build (although it is originated
from Maven-Central), the 'maven-slf4j-provider' jar embedded into the
m2e.maven.runtime is not jar signed (because nested jars are not
signed).
Extracting the jar and providing them from a directory
This check is not performed if a jar is extracted and added to the
classpath as directory. Therefore only the slf4j jar is extracted again.
Effectively this reverts commit 143c182
for slf4j.

Additionally this ensures that paths to jars are canonicalized.
  • Loading branch information
HannesWell committed Oct 1, 2022
1 parent 143c182 commit 1d0fb2c
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 19 deletions.
29 changes: 15 additions & 14 deletions org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/Bundles.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private Bundles() {

private static final Logger log = LoggerFactory.getLogger(Bundles.class);

public static List<String> getClasspathEntries(Bundle bundle) {
public static List<String> getClasspathEntries(Bundle bundle, boolean extractRoot) {
log.debug("getClasspathEntries(Bundle={})", bundle);
Set<String> cp = new LinkedHashSet<>();
if(inDevelopmentMode()) {
Expand All @@ -53,13 +53,7 @@ public static List<String> getClasspathEntries(Bundle bundle) {
cp.addAll(parseBundleClasspath(bundle));
List<String> entries = new ArrayList<>();
for(String cpe : cp) {
String entry;
if(".".equals(cpe)) {
entry = FileLocator.getBundleFileLocation(bundle)
.orElseThrow(() -> new NoSuchElementException("Unable to locate bundle:" + bundle)).toString();
} else {
entry = getClasspathEntryPath(bundle, cpe);
}
String entry = getClasspathEntryPath(bundle, cpe, extractRoot);
if(entry != null) {
log.debug("\tEntry:{}", entry);
entries.add(entry);
Expand All @@ -81,16 +75,23 @@ private static List<String> parseBundleClasspath(Bundle bundle) {
return List.of(".");
}

public static String getClasspathEntryPath(Bundle bundle, String cp) {
public static String getClasspathEntryPath(Bundle bundle, String cp, boolean extractRoot) {
// try embedded entries first
URL url = bundle.getEntry(cp);
if(url != null) {
try {
try {
if(".".equals(cp)) {
if(!extractRoot) {
return FileLocator.getBundleFileLocation(bundle)
.orElseThrow(() -> new NoSuchElementException("Unable to locate bundle:" + bundle)).getCanonicalPath();
}
cp = "/"; // get bundle's root entry below, which extracts the bundle's jar, if it not of shape 'dir' already
}
URL url = bundle.getEntry(cp);
if(url != null) {
String path = FileLocator.toFileURL(url).getFile();
return new Path(path).toOSString();
} catch(IOException ex) {
log.warn("Could not get entry {} for bundle {}", cp, bundle, ex);
}
} catch(IOException ex) {
log.warn("Could not get entry {} for bundle {}", cp, bundle, ex);
}

// in development mode entries can be absolute paths outside of bundle basedir
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ public void createLauncherConfiguration(IMavenLauncherConfiguration collector, I
}
}

public static final Set<String> SLF4J_BUNDLE_NAMES = Set.of("org.slf4j.api", "slf4j.api");

private synchronized void initClasspath() {
if(CLASSPATH == null) {
Bundle mavenRuntimeBundle = findMavenEmbedderBundle();
Expand All @@ -120,9 +122,8 @@ private synchronized void initClasspath() {
addBundleClasspathEntries(allEntries, mavenRuntimeBundle, true);
allEntries.add(getEmbeddedSLF4JBinding(mavenRuntimeBundle));

Set<String> noDependencyBundles = Set.of("org.slf4j.api", "slf4j.api");
// Don't include dependencies of slf4j bundle to ensure no other than the slf4j-binding embedded into m2e.maven.runtime is available.
Set<Bundle> bundles = getRequiredBundles(mavenRuntimeBundle, noDependencyBundles);
Set<Bundle> bundles = getRequiredBundles(mavenRuntimeBundle, SLF4J_BUNDLE_NAMES);

for(Bundle bundle : bundles) {
addBundleClasspathEntries(allEntries, bundle, false);
Expand All @@ -141,11 +142,13 @@ private synchronized void initClasspath() {
}

private void addBundleClasspathEntries(Set<String> entries, Bundle bundle, boolean addFragments) {
entries.addAll(Bundles.getClasspathEntries(bundle));
boolean extractRoot = SLF4J_BUNDLE_NAMES.contains(bundle.getSymbolicName());
// Use extracted/directory form of slf4j bundles so that their jar-signing signature by the Maven-runtime classloader
entries.addAll(Bundles.getClasspathEntries(bundle, extractRoot));
Bundle[] fragments;
if(addFragments && (fragments = Platform.getFragments(bundle)) != null) {
for(Bundle fragment : fragments) {
entries.addAll(Bundles.getClasspathEntries(fragment));
entries.addAll(Bundles.getClasspathEntries(fragment, SLF4J_BUNDLE_NAMES.contains(fragment.getSymbolicName())));
}
}
}
Expand All @@ -154,7 +157,7 @@ private static String getEmbeddedSLF4JBinding(Bundle mavenBundle) {
String bindingPath = mavenBundle.getHeaders().get(M2E_SL4J_BINDING_HEADER);
Objects.requireNonNull(bindingPath,
() -> "Missing '" + M2E_SL4J_BINDING_HEADER + "' header in embedded Maven-runtime bundle");
String bindingJarPath = Bundles.getClasspathEntryPath(mavenBundle, bindingPath);
String bindingJarPath = Bundles.getClasspathEntryPath(mavenBundle, bindingPath, false);
return Objects.requireNonNull(bindingJarPath, () -> M2E_SL4J_BINDING_HEADER + " '" + bindingPath + "' not found");
}

Expand Down

0 comments on commit 1d0fb2c

Please sign in to comment.