Avoid compatibility check failure for Uber JARs and Universal Binaries#3082
Avoid compatibility check failure for Uber JARs and Universal Binaries#3082HeikoKlare wants to merge 1 commit intoeclipse-platform:masterfrom
Conversation
When packaging SWT into an Uber Jar or using universal binaries (for multiple architectures), the Jar manifest cannot reference a single OS and/or architecture. As a result, the compatibility check implemented in Library.isLaodable() can never succeed for such a packaging. With those compatibility checks always being executed upon initialization of SWT with a recent change, using such packaging of SWT became difficult or impossible. This change makes the initialization of SWT not fail in case the JAR manifest is completely lacking the according entries for OS and architecture. This will still make the initialization fail if an OS and/or architecture is specified in the manifest that is incompatible to the current environment, but in case the manifest does not contain such entries, the library will just (try to) boot. The behavior of Platform.isLoadable() is preserved. That method will still return false in case the Manifest does not contain according entries, as this is the long-standing behavior of that method. Fixes eclipse-platform#2928
|
@openaudible would this solution be fine for you? |
There was a problem hiding this comment.
I would say it might do the trick, but you've introduced complexity and the default isLoadable will still return false negatives.
In my opinion:
- isLoadable is simply a way for exitIfNotLoadable to catch the case where a developer or user tries to launch SWT code with the wrong jar.
- Thus, isLoadable should provide a detailed error message right before System.exit is called.
- isLoadable should not return false unless it is guaranteed to be not loadable. (No false negatives!)
- loadLibrary failing with one or more error messages has been the real long-standing behavior of SWT. The manifest check was introduced last year.
This function accomplishes the above and doesn't require changes to each Platform. It gives a highly detailed error message which should make it clear exactly which jar is causing the problem and what the architecture mismatch is.
static boolean isLoadable() {
URL url = Platform.class.getClassLoader().getResource("org/eclipse/swt/internal/Library.class"); //$NON-NLS-1$
if (!url.getProtocol().equals("jar")) { //$NON-NLS-1$
/* SWT is presumably running in a development environment */
return true;
}
String jarPath = null;
Attributes attributes = null;
try {
URLConnection connection = url.openConnection();
if (!(connection instanceof JarURLConnection jc)) {
/* should never happen for a "jar:" url */
return false;
}
attributes = jc.getMainAttributes();
jarPath = jc.getJarFileURL().getPath();
} catch (IOException e) {
/* should never happen for a valid SWT jar with the expected manifest values */
return false;
}
String manifestOS = attributes.getValue("SWT-OS"); //$NON-NLS-1$
String manifestArch = attributes.getValue("SWT-Arch"); //$NON-NLS-1$
// Missing: allow (uber JAR or universal binary) where manifest entries are stripped
if (manifestOS == null || manifestArch == null) {
return true;
}
String os = os();
String arch = arch();
// Present but mismatched: fail with clear diagnostic
if (!arch.equals(manifestArch) || !os.equals(manifestOS)) {
System.err.println("org.eclipse.swt platform mismatch for jar: " + jarPath);
System.err.println(" Manifest: SWT-OS=" + manifestOS + ", SWT-Arch=" + manifestArch);
System.err.println(" Runtime: os=" + os + ", arch=" + arch);
return false;
}
return true;
}
Respectfully,
|
In general, I share your opinion on the expectation of when In case we agree that changing the behavior of |
|
If you're happy with it, then it's fine with me. |
When packaging SWT into an Uber Jar or using universal binaries (for multiple architectures), the Jar manifest cannot reference a single OS and/or architecture. As a result, the compatibility check implemented in Library.isLaodable() can never succeed for such a packaging. With those compatibility checks always being executed upon initialization of SWT with a recent change, using such packaging of SWT became difficult or impossible.
This change makes the initialization of SWT not fail in case the JAR manifest is completely lacking the according entries for OS and architecture. This will still make the initialization fail if an OS and/or architecture is specified in the manifest that is incompatible to the current environment, but in case the manifest does not contain such entries, the library will just (try to) boot. The behavior of Platform.isLoadable() is preserved. That method will still return false in case the Manifest does not contain according entries, as this is the long-standing behavior of that method.
Fixes #2928