diff --git a/build/org.eclipse.pde.build/src/org/eclipse/pde/internal/build/site/PDEState.java b/build/org.eclipse.pde.build/src/org/eclipse/pde/internal/build/site/PDEState.java index ad4468b34f2..e34dcb87a86 100644 --- a/build/org.eclipse.pde.build/src/org/eclipse/pde/internal/build/site/PDEState.java +++ b/build/org.eclipse.pde.build/src/org/eclipse/pde/internal/build/site/PDEState.java @@ -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 @@ -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; @@ -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; @@ -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; @@ -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 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 targetVMSystemPackages = querySystemPackages(targetVM, null); + if (targetVMSystemPackages == null) { + return null; + } + Stream targetVMNonJavaPackages = targetVMSystemPackages.stream().filter(p -> !p.startsWith("java.")); //$NON-NLS-1$ + Stream 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> 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 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 querySystemPackages(IVMInstall vm, IExecutionEnvironment environment) { + if (!JavaRuntime.isModularJava(vm)) { + Collection 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 packages = new TreeSet<>(); + Collection 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); @@ -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 nonStrictDefaultSelector) { IVMInstall defaultVM = environment.getDefaultVM(); if (defaultVM != null) { return defaultVM; @@ -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() { diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TargetPlatformHelper.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TargetPlatformHelper.java index 949274f5af4..e23f03d91c9 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TargetPlatformHelper.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/TargetPlatformHelper.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corporation and others. + * Copyright (c) 2000, 2023 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -22,7 +22,6 @@ import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; @@ -45,8 +44,6 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; -import org.eclipse.jdt.core.JavaCore; -import org.eclipse.jdt.launching.IVMInstall; import org.eclipse.jdt.launching.JavaRuntime; import org.eclipse.jdt.launching.environments.IExecutionEnvironment; import org.eclipse.osgi.service.resolver.BundleDescription; @@ -354,14 +351,11 @@ public static Dictionary getTargetEnvironment(MinimalState state } @SuppressWarnings("unchecked") - public static Dictionary[] getPlatformProperties(String[] profiles, MinimalState state) { - if (profiles == null || profiles.length == 0) { - return new Dictionary[] { getTargetEnvironment(state) }; - } - + public static Dictionary[] getPlatformProperties(String[] profilesArr, MinimalState state) { + List profiles = profilesArr != null ? Arrays.asList(profilesArr) : List.of(); // add java profiles for those EE's that have a .profile file in the // current system bundle - List> result = new ArrayList<>(profiles.length); + List> result = new ArrayList<>(profiles.size()); for (String profile : profiles) { IExecutionEnvironment environment = JavaRuntime.getExecutionEnvironmentsManager().getEnvironment(profile); if (environment != null) { @@ -381,11 +375,10 @@ public static Dictionary[] getPlatformProperties(String[] profil public static void addEnvironmentProperties(Dictionary properties, IExecutionEnvironment environment, Properties profileProps) { - String systemPackages = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES); - if (systemPackages == null) { // java 10 and beyond - systemPackages = querySystemPackages(environment); - } + String systemPackages = querySystemPackages(environment); if (systemPackages != null) { + // The list of system-packages is often insufficient, always + // overwrite, if we have a more up-to-date one properties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages); } @SuppressWarnings("deprecation") @@ -396,54 +389,8 @@ public static void addEnvironmentProperties(Dictionary propertie } } - @SuppressWarnings("restriction") public static String querySystemPackages(IExecutionEnvironment environment) { - IVMInstall vm = bestVmInstallFor(environment); - if (vm == null || !JavaRuntime.isModularJava(vm)) { - return null; - } - String release = environment.getProfileProperties().getProperty(JavaCore.COMPILER_COMPLIANCE); - try { - Collection packages = new TreeSet<>(); - 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); - for (String moduleName : jrt.getModuleNames(null)) { - var module = jrt.getModule(moduleName); - if (module == null) { - continue; - } - for (var packageExport : module.exports()) { - if (!packageExport.isQualified()) { - packages.add(new String(packageExport.name())); - } - } - } - return String.join(",", packages); //$NON-NLS-1$ - } catch (CoreException e) { - PDECore.logException(e, "failed to read system packages for " + environment); //$NON-NLS-1$ - } - return null; - } - - private static IVMInstall bestVmInstallFor(IExecutionEnvironment environment) { - if (environment == null) { - return null; - } - IVMInstall defaultVM = environment.getDefaultVM(); - if (defaultVM != null) { - return defaultVM; - } - IVMInstall[] compatible = environment.getCompatibleVMs(); - if (compatible.length == 0) { - return null; - } - for (IVMInstall vm : compatible) { - if (environment.isStrictlyCompatible(vm)) { - return vm; - } - } - return compatible[0]; + return org.eclipse.pde.internal.build.site.PDEState.querySystemPackages(environment); } public static String[] getKnownExecutionEnvironments() { diff --git a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/launcher/LaunchValidationOperation.java b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/launcher/LaunchValidationOperation.java index 58d6b1da974..0d481473794 100644 --- a/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/launcher/LaunchValidationOperation.java +++ b/ui/org.eclipse.pde.launching/src/org/eclipse/pde/internal/launching/launcher/LaunchValidationOperation.java @@ -17,10 +17,8 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.Arrays; import java.util.Dictionary; -import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -60,27 +58,22 @@ public void run(IProgressMonitor monitor) throws CoreException { @SuppressWarnings("unchecked") protected Dictionary[] getPlatformProperties() throws CoreException { IExecutionEnvironment[] envs = getMatchingEnvironments(); - if (envs.length == 0) { - return new Dictionary[] {TargetPlatformHelper.getTargetEnvironment()}; - } - // add java profiles for those EE's that have a .profile file in the current system bundle - List> result = new ArrayList<>(envs.length); - for (IExecutionEnvironment env : envs) { + Dictionary environmentProperties = TargetPlatformHelper.getTargetEnvironment(); + // Only add the highest EE of the supplied VM, to match the runtime behavior + for (int i = envs.length - 1; i > 0; i--) { + IExecutionEnvironment env = envs[i]; + // add java profiles for those EE's that have a .profile file in the current system bundle Properties profileProps = getJavaProfileProperties(env.getId()); if (profileProps == null) { // Java10 onwards, we take profile via this method profileProps = env.getProfileProperties(); } if (profileProps != null) { - Dictionary props = TargetPlatformHelper.getTargetEnvironment(); - TargetPlatformHelper.addEnvironmentProperties(props, env, profileProps); - result.add(props); + TargetPlatformHelper.addEnvironmentProperties(environmentProperties, env, profileProps); + break; } } - if (!result.isEmpty()) { - return result.toArray(Dictionary[]::new); - } - return new Dictionary[] {TargetPlatformHelper.getTargetEnvironment()}; + return new Dictionary[] {environmentProperties}; } protected IExecutionEnvironment[] getMatchingEnvironments() throws CoreException {