Skip to content

Commit

Permalink
Enhance computation of system-package provided by a ExecutionEnvironment
Browse files Browse the repository at this point in the history
- Only consider EE of running VM in launch validation to match the
behavior later at runtime
- For the PDEState the EE's system-package is computed with the
following distinction:
  - for a EE that corresponds to a Java-9 or higher release, get the
  'best matching' VMInstall and query the system-packages for the EE's
  java release version (which is possible for modular JVMs)
  - for a Java-8 or lower release check if there is a VMInstall
  selected/strictly compatible to that version and query the
  system-packages from that VM (i.e. its rt.jar and other libraries)
  - if there is no VMInstall for a for a Java-8 or lower release,
  combine the hard-coded list of 'java.*' packages with the set of
  non-java packages provided by the default VMInstall of the workspace.
  The default VMInstall of the WS is at the same time the JVM selected
  in the active target definition (which sets its selection as WS
  default upon loading).

Fixes eclipse-pde#429
  • Loading branch information
HannesWell committed Aug 3, 2023
1 parent 9b8d81e commit d1dc6e5
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 95 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2021 IBM Corporation and others.
* Copyright (c) 2004, 2023 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand All @@ -10,6 +10,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
* Hannes Wellmann - Enhance computation of system-package provided by a ExecutionEnvironment
*******************************************************************************/
package org.eclipse.pde.internal.build.site;

Expand All @@ -30,8 +31,9 @@
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.jar.JarFile;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

Expand All @@ -44,6 +46,7 @@
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.LibraryLocation;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.ExportPackageDescription;
Expand Down Expand Up @@ -481,14 +484,215 @@ public void resolveState() {
}

public static String querySystemPackages(IExecutionEnvironment environment) {
// Copy of org.eclipse.pde.internal.core.TargetPlatformHelper.querySystemPackages()
IVMInstall vm = bestVmInstallFor(environment);
if (vm == null || !JavaRuntime.isModularJava(vm)) {
if (environment == null) {
return null;
}
Integer releaseVersion = readJavaReleaseVersion(environment);
if (releaseVersion == null) {
return null;
}
String release = environment.getProfileProperties().getProperty(JavaCore.COMPILER_COMPLIANCE);
Collection<String> systemPackages;
if (releaseVersion <= 8) {
IVMInstall eeVM = environment.getDefaultVM();
IVMInstall vm = bestVmInstallFor(environment, vms -> null); // TODO: also consider perfect matches?
if (eeVM != null) {
// In case a VM is selected for an EE, query that VM and use its system-packages
systemPackages = querySystemPackages(eeVM, null);
} else {
// No VM selected for the non-modular EE, compose list of available system-packages from the predefined list of java-packages plus the non-java packages of the WS default VM
IVMInstall targetVM = JavaRuntime.getDefaultVMInstall(); // Set by the Target-Definition if specified there
Collection<String> targetVMSystemPackages = querySystemPackages(targetVM, null);
if (targetVMSystemPackages == null) {
return null;
}
Stream<String> targetVMNonJavaPackages = targetVMSystemPackages.stream().filter(p -> !p.startsWith("java.")); //$NON-NLS-1$
Stream<String> javaPackages = PRE_JAVA_9_SYSTEM_PACKAGES.get(releaseVersion).stream();
systemPackages = Stream.concat(javaPackages, targetVMNonJavaPackages).sorted().toList();
}
} else {
IVMInstall vm = bestVmInstallFor(environment, vms -> vms[0]);
if (vm == null) {
return null;
}
systemPackages = querySystemPackages(vm, environment);
}
return String.join(",", systemPackages); //$NON-NLS-1$
}

//TODO: fill empty lists
@SuppressWarnings("nls")
private static final List<List<String>> PRE_JAVA_9_SYSTEM_PACKAGES = List.of(
// Java 1.0
List.of(),
// Java 1.1
List.of(),
// Java 1.2
List.of("java.applet", //
"java.awt", //
"java.awt.color", //
"java.awt.datatransfer", //
"java.awt.dnd", //
"java.awt.dnd.peer", //
"java.awt.event", //
"java.awt.font", //
"java.awt.geom", //
"java.awt.im", //
"java.awt.image", //
"java.awt.image.renderable", //
"java.awt.peer", //
"java.awt.print", //
"java.awt.resources", //
"java.beans", //
"java.beans.beancontext", //
"java.io", //
"java.lang", //
"java.lang.ref", //
"java.lang.reflect", //
"java.math", //
"java.net", //
"java.rmi", //
"java.rmi.activation", //
"java.rmi.dgc", //
"java.rmi.registry", //
"java.rmi.server", //
"java.security", //
"java.security.acl", //
"java.security.cert", //
"java.security.interfaces", //
"java.security.spec", //
"java.sql", //
"java.text", //
"java.text.resources", //
"java.util", //
"java.util.jar", //
"java.util.zip"),
// Java 1.3
List.of(),
// Java 1.4
List.of(),
// Java 1.5
List.of(),
// Java 1.6
List.of(),
// Java 1.7
List.of(),
// Java 1.8
List.of("java.applet", //
"java.awt", //
"java.awt.color", //
"java.awt.datatransfer", //
"java.awt.dnd", //
"java.awt.dnd.peer", //
"java.awt.event", //
"java.awt.font", //
"java.awt.geom", //
"java.awt.im", //
"java.awt.im.spi", //
"java.awt.image", //
"java.awt.image.renderable", //
"java.awt.peer", //
"java.awt.print", //
"java.beans", //
"java.beans.beancontext", //
"java.io", //
"java.lang", //
"java.lang.annotation", //
"java.lang.instrument", //
"java.lang.invoke", //
"java.lang.management", //
"java.lang.ref", //
"java.lang.reflect", //
"java.math", //
"java.net", //
"java.nio", //
"java.nio.channels", //
"java.nio.channels.spi", //
"java.nio.charset", //
"java.nio.charset.spi", //
"java.nio.file", //
"java.nio.file.attribute", //
"java.nio.file.spi", //
"java.rmi", //
"java.rmi.activation", //
"java.rmi.dgc", //
"java.rmi.registry", //
"java.rmi.server", //
"java.security", //
"java.security.acl", //
"java.security.cert", //
"java.security.interfaces", //
"java.security.spec", //
"java.sql", //
"java.text", //
"java.text.spi", //
"java.time", //
"java.time.chrono", //
"java.time.format", //
"java.time.temporal", //
"java.time.zone", //
"java.util", //
"java.util.concurrent", //
"java.util.concurrent.atomic", //
"java.util.concurrent.locks", //
"java.util.function", //
"java.util.jar", //
"java.util.logging", //
"java.util.prefs", //
"java.util.regex", //
"java.util.spi", //
"java.util.stream", //
"java.util.zip"));

@SuppressWarnings("nls")
private static final Map<String, Integer> JDK_ID_RELEASE = Map.of( //
//TODO: add zero?
"JRE-1.1", 1, //
"J2SE-1.2", 2, //
"J2SE-1.3", 3, //
"J2SE-1.4", 4, //
"J2SE-1.5", 5, //
"JavaSE-1.6", 6, //
"JavaSE-1.7", 7, //
"JavaSE-1.8", 8);

private static Integer readJavaReleaseVersion(IExecutionEnvironment environment) {
String id = environment.getId();
if (id.startsWith("JavaSE-")) { //$NON-NLS-1$
try {
return Integer.parseInt(id.substring("JavaSE-".length())); //$NON-NLS-1$
} catch (NumberFormatException e) { // Another EE
}
}
return JDK_ID_RELEASE.get(id);
}

/**
* Returns t
* @param vm the VM to query
* @param environment the release EE to use or null, if the VM's release should be used
*/
private static Collection<String> querySystemPackages(IVMInstall vm, IExecutionEnvironment environment) {
if (!JavaRuntime.isModularJava(vm)) {
Collection<String> packages = new HashSet<>();
for (LibraryLocation libLocation : JavaRuntime.getLibraryLocations(vm)) {
IPath path = libLocation.getSystemLibraryPath();
if (path != null) {
try (ZipFile zip = new ZipFile(path.toFile())) {
zip.stream().filter(e -> !e.isDirectory()).map(ZipEntry::getName).filter(n -> !n.startsWith("META-INF/")).map(n -> { //$NON-NLS-1$
int i = n.lastIndexOf('/');
return n.substring(0, i);
}).distinct().map(n -> n.replace('/', '.')).forEach(packages::add);
} catch (IOException e) {
ILog.get().error("Failed to read packages in JVM library for " + vm + ", at " + path, e); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
return packages;
}

String release = environment != null ? environment.getProfileProperties().getProperty(JavaCore.COMPILER_COMPLIANCE) : null;
try {
Collection<String> packages = new TreeSet<>();
Collection<String> packages = new HashSet<>();
String jrtPath = "lib/" + org.eclipse.jdt.internal.compiler.util.JRTUtil.JRT_FS_JAR; //$NON-NLS-1$
String path = new File(vm.getInstallLocation(), jrtPath).toString(); // $NON-NLS-1$
var jrt = org.eclipse.jdt.internal.core.builder.ClasspathLocation.forJrtSystem(path, null, null, release);
Expand All @@ -503,17 +707,14 @@ public static String querySystemPackages(IExecutionEnvironment environment) {
}
}
}
return String.join(",", packages); //$NON-NLS-1$
return packages;
} catch (CoreException e) {
ILog.of(PDEState.class).log(Status.error("failed to read system packages for " + environment, e)); //$NON-NLS-1$
ILog.of(PDEState.class).log(Status.error("Failed to read system packages for " + environment, e)); //$NON-NLS-1$
}
return null;
}

private static IVMInstall bestVmInstallFor(IExecutionEnvironment environment) {
if (environment == null) {
return null;
}
private static IVMInstall bestVmInstallFor(IExecutionEnvironment environment, Function<IVMInstall[], IVMInstall> nonStrictDefaultSelector) {
IVMInstall defaultVM = environment.getDefaultVM();
if (defaultVM != null) {
return defaultVM;
Expand All @@ -522,12 +723,8 @@ private static IVMInstall bestVmInstallFor(IExecutionEnvironment environment) {
if (compatible.length == 0) {
return null;
}
for (IVMInstall vm : compatible) {
if (environment.isStrictlyCompatible(vm)) {
return vm;
}
}
return compatible[0];
IVMInstall nonStrictDefault = nonStrictDefaultSelector.apply(compatible);
return Arrays.stream(compatible).filter(environment::isStrictlyCompatible).findFirst().orElse(nonStrictDefault);
}

public State getState() {
Expand Down
Loading

0 comments on commit d1dc6e5

Please sign in to comment.