Skip to content
Closed

Pr 2013 #2029

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<feature
id="org.eclipse.pde.unittest.junit"
label="%featureName"
version="1.0.1100.qualifier"
version="1.0.1200.qualifier"
provider-name="%providerName"
license-feature="org.eclipse.license"
license-feature-version="0.0.0">
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.pde.doc.user/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.pde.doc.user; singleton:=true
Bundle-Version: 3.17.300.qualifier
Bundle-Version: 3.17.400.qualifier
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Require-Bundle: org.eclipse.help;bundle-version="[3.2.0,4.0.0)"
2 changes: 1 addition & 1 deletion org.eclipse.pde.doc.user/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<version>4.38.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.pde.doc.user</artifactId>
<version>3.17.300-SNAPSHOT</version>
<version>3.17.400-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.eclipse.core.resources.IResourceChangeEvent;
Expand Down Expand Up @@ -56,6 +59,8 @@
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.Version;
import org.osgi.framework.VersionRange;
import org.osgi.util.tracker.ServiceTracker;

import aQute.bnd.build.Workspace;
Expand Down Expand Up @@ -109,7 +114,7 @@
*/
private static PDEPreferencesManager fPreferenceManager;

private Map<String, IPluginModelBase> fHostPlugins;
private Map<String, List<IPluginModelBase>> fHostPlugins;

public static PDECore getDefault() {
return inst;
Expand Down Expand Up @@ -221,7 +226,28 @@
inst = this;
}

public synchronized IPluginModelBase findPluginInHost(String id) {
public synchronized IPluginModelBase findPluginInHost(String id, VersionRange version) {
Map<String, List<IPluginModelBase>> hostPlugins = getHostPlugins();
if (hostPlugins == null) {
return null;
}
Stream<IPluginModelBase> plugins = hostPlugins.getOrDefault(id, List.of()).stream();
if (version != null) {
plugins = plugins.filter(p -> version.includes(getVersion(p)));
}
return plugins.max(VERSION).orElse(null);
}

private static final Comparator<IPluginModelBase> VERSION = Comparator.comparing(PDECore::getVersion);

private static Version getVersion(IPluginModelBase p) {
// TODO: Check the following also works for plugins from host. If yes,
// use it.
Version version2 = p.getBundleDescription().getVersion();

Check warning on line 246 in ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/PDECore.java

View check run for this annotation

Jenkins - eclipse-pde / Compiler

Unnecessary Code

NORMAL: The value of the local variable version2 is not used
return Version.parseVersion(p.getPluginBase().getVersion());
}

private synchronized Map<String, List<IPluginModelBase>> getHostPlugins() {
if (fHostPlugins == null) {
fHostPlugins = new HashMap<>();

Expand All @@ -239,12 +265,10 @@
PDEState state = new PDEState(pluginPaths, true, false, new NullProgressMonitor());
state.resolveState(false);

for (IPluginModelBase plugin : state.getTargetModels()) {
fHostPlugins.put(plugin.getPluginBase().getId(), plugin);
}
fHostPlugins = Arrays.stream(state.getTargetModels())
.collect(Collectors.groupingBy(p -> p.getPluginBase().getId()));
}

return fHostPlugins.get(id);
return fHostPlugins;
}

public PluginModelManager getModelManager() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*******************************************************************************
* Copyright (c) 2006, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Advantest - GH issue 2006 - JUnit 5 bundle clashes with JUnit 6
*******************************************************************************/
package org.eclipse.pde.internal.launching;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.internal.core.DependencyManager;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.launching.launcher.BundleLauncherHelper;
import org.osgi.framework.Version;
import org.osgi.framework.VersionRange;
import org.osgi.framework.wiring.BundleRevision;

public class JUnitLaunchRequirements {

public static final String JUNIT4_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit4.runtime"; //$NON-NLS-1$
public static final String JUNIT5_JDT_RUNTIME_PLUGIN = "org.eclipse.jdt.junit5.runtime"; //$NON-NLS-1$

private static final VersionRange JUNIT5_VERSIONS = new VersionRange("[1, 6)"); //$NON-NLS-1$

// we add launcher and jupiter.engine to support @RunWith(JUnitPlatform.class)
private static final Map<String, List<String>> JUNIT5_RUN_WITH_BUNDLES = new LinkedHashMap<>();
static { // consider JUnit bundle names from old Eclipse-Orbit times. Assume either only new or only old names are used.
JUNIT5_RUN_WITH_BUNDLES.put("junit-platform-runner", List.of("junit-platform-launcher", "junit-jupiter-engine")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
JUNIT5_RUN_WITH_BUNDLES.put("org.junit.platform.runner", List.of("org.junit.platform.launcher", "org.junit.jupiter.engine")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}

public static void addRequiredJunitRuntimePlugins(ILaunchConfiguration configuration, Map<String, List<IPluginModelBase>> allBundles, Map<IPluginModelBase, String> allModels) throws CoreException {
Collection<String> runtimePlugins = getRequiredJunitRuntimeEclipsePlugins(configuration);

Set<BundleDescription> addedRuntimeBundles = addAbsentRequirements(runtimePlugins, allBundles, allModels);
Set<BundleDescription> runtimeRequirements = DependencyManager.findRequirementsClosure(addedRuntimeBundles);
addAbsentRequirements(runtimeRequirements, allBundles, allModels);

if (runtimePlugins.contains(JUNIT5_JDT_RUNTIME_PLUGIN)) {
Optional<List<String>> runWithBundles = JUNIT5_RUN_WITH_BUNDLES.entrySet().stream().filter(e -> allBundles.containsKey(e.getKey())).findFirst().map(Entry::getValue);
if (runWithBundles.isPresent()) {
Set<BundleDescription> descriptions = findBundlesInTargetOrHost(runWithBundles.get(), JUNIT5_VERSIONS);
Set<BundleDescription> junitRquirements = DependencyManager.findRequirementsClosure(descriptions);
addAbsentRequirements(junitRquirements, allBundles, allModels);
}
}
}

@SuppressWarnings("restriction")
public static Collection<String> getRequiredJunitRuntimeEclipsePlugins(ILaunchConfiguration configuration) {
org.eclipse.jdt.internal.junit.launcher.ITestKind testKind = org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants.getTestRunnerKind(configuration);
if (testKind.isNull()) {
return List.of();
}
List<String> plugins = new ArrayList<>();
plugins.add("org.eclipse.pde.junit.runtime"); //$NON-NLS-1$
switch (testKind.getId()) {
case org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT3_TEST_KIND_ID -> {
} // Nothing to add for JUnit-3
case org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT4_TEST_KIND_ID -> plugins.add(JUNIT4_JDT_RUNTIME_PLUGIN);
case org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT5_TEST_KIND_ID -> plugins.add(JUNIT5_JDT_RUNTIME_PLUGIN);
default -> throw new IllegalArgumentException("Unsupported junit test kind: " + testKind.getId()); //$NON-NLS-1$
}
return plugins;
}

private static Set<BundleDescription> addAbsentRequirements(Collection<String> requirements, Map<String, List<IPluginModelBase>> allBundles, Map<IPluginModelBase, String> allModels) throws CoreException {
Set<BundleDescription> addedRequirements = new LinkedHashSet<>();
for (String id : requirements) {
List<IPluginModelBase> models = allBundles.computeIfAbsent(id, k -> new ArrayList<>());
if (models.stream().noneMatch(p -> p.getBundleDescription().isResolved())) {
IPluginModelBase model = findRequiredPluginInTargetOrHost(id, null);
models.add(model);
BundleLauncherHelper.addDefaultStartingBundle(allModels, model);
addedRequirements.add(model.getBundleDescription());
}
}
return addedRequirements;
}

private static void addAbsentRequirements(Set<BundleDescription> requirements, Map<String, List<IPluginModelBase>> allBundles, Map<IPluginModelBase, String> allModels) throws CoreException {
for (BundleRevision requirement : requirements) {
String id = requirement.getSymbolicName();
Version version = requirement.getVersion();
List<IPluginModelBase> models = allBundles.computeIfAbsent(id, k -> new ArrayList<>());
boolean replace = !models.isEmpty() && models.stream().anyMatch(m -> !m.getBundleDescription().getVersion().equals(version));
if (replace || models.stream().noneMatch(m -> m.getBundleDescription().isResolved())) {
IPluginModelBase model = findRequiredPluginInTargetOrHost(requirement.getSymbolicName(), new VersionRange(VersionRange.LEFT_CLOSED, version, version, VersionRange.RIGHT_CLOSED));
if (replace) {
String startLevel = null;
for (IPluginModelBase m : models) {
startLevel = allModels.remove(m);
}
models.clear();
allModels.put(model, startLevel); //TODO: isn't this overwritten? Should it be retained or just ignored?
}
models.add(model);
BundleLauncherHelper.addDefaultStartingBundle(allModels, model);
}
}
}

private static Set<BundleDescription> findBundlesInTargetOrHost(List<String> bundleIDs, VersionRange version) throws CoreException {
Set<BundleDescription> descriptions = new LinkedHashSet<>();
for (String id : bundleIDs) {
IPluginModelBase model = findRequiredPluginInTargetOrHost(id, version);
if (model != null) {
descriptions.add(model.getBundleDescription());
}
}
return descriptions;
}

private static IPluginModelBase findRequiredPluginInTargetOrHost(String id, VersionRange version) throws CoreException {
IPluginModelBase model = version != null ? PluginRegistry.findModel(id, version) : PluginRegistry.findModel(id);
if (model == null || !model.getBundleDescription().isResolved()) {
// prefer bundle from host over unresolved bundle from target
model = PDECore.getDefault().findPluginInHost(id, version);
}
if (model == null) {
throw new CoreException(Status.error(NLS.bind(PDEMessages.JUnitLaunchConfiguration_error_missingPlugin, id)));
}
return model;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,12 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
Expand All @@ -58,7 +54,6 @@
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.IVMRunner;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.plugin.IFragment;
Expand All @@ -69,14 +64,13 @@
import org.eclipse.pde.core.plugin.TargetPlatform;
import org.eclipse.pde.internal.build.IPDEBuildConstants;
import org.eclipse.pde.internal.core.ClasspathHelper;
import org.eclipse.pde.internal.core.DependencyManager;
import org.eclipse.pde.internal.core.ICoreConstants;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.TargetPlatformHelper;
import org.eclipse.pde.internal.core.bnd.PdeProjectAnalyzer;
import org.eclipse.pde.internal.core.util.CoreUtility;
import org.eclipse.pde.internal.core.util.VersionUtil;
import org.eclipse.pde.internal.launching.IPDEConstants;
import org.eclipse.pde.internal.launching.JUnitLaunchRequirements;
import org.eclipse.pde.internal.launching.PDELaunchingPlugin;
import org.eclipse.pde.internal.launching.PDEMessages;
import org.eclipse.pde.internal.launching.launcher.BundleLauncherHelper;
Expand Down Expand Up @@ -393,18 +387,6 @@ protected String getApplication(ILaunchConfiguration configuration) {
return application;
}

private IPluginModelBase findRequiredPluginInTargetOrHost(String id) throws CoreException {
IPluginModelBase model = PluginRegistry.findModel(id);
if (model == null || !model.getBundleDescription().isResolved()) {
// prefer bundle from host over unresolved bundle from target
model = PDECore.getDefault().findPluginInHost(id);
}
if (model == null) {
abort(NLS.bind(PDEMessages.JUnitLaunchConfiguration_error_missingPlugin, id), null, IStatus.OK);
}
return model;
}

@Override
public String getProgramArguments(ILaunchConfiguration configuration) throws CoreException {
return LaunchArgumentsHelper.getUserProgramArguments(configuration);
Expand Down Expand Up @@ -537,7 +519,7 @@ protected void preLaunchCheck(ILaunchConfiguration configuration, ILaunch launch
launchMode = launch.getLaunchMode();

// implicitly add the plug-ins required for JUnit testing if necessary
addRequiredJunitRuntimePlugins(configuration);
JUnitLaunchRequirements.addRequiredJunitRuntimePlugins(configuration, fAllBundles, fModels);

String attribute = launch.getAttribute(PDE_JUNIT_SHOW_COMMAND);
boolean isShowCommand = false;
Expand All @@ -558,58 +540,6 @@ protected void preLaunchCheck(ILaunchConfiguration configuration, ILaunch launch
synchronizeManifests(configuration, subMonitor.split(1));
}

private void addRequiredJunitRuntimePlugins(ILaunchConfiguration configuration) throws CoreException {
Set<String> requiredPlugins = new LinkedHashSet<>(getRequiredJunitRuntimePlugins(configuration));

if (fAllBundles.containsKey("junit-platform-runner") || fAllBundles.containsKey("org.junit.platform.runner")) { //$NON-NLS-1$ //$NON-NLS-2$
// add launcher and jupiter.engine to support @RunWith(JUnitPlatform.class)
requiredPlugins.add("junit-platform-launcher"); //$NON-NLS-1$
requiredPlugins.add("junit-jupiter-engine"); //$NON-NLS-1$
}
Set<BundleDescription> addedRequirements = new HashSet<>();
addAbsentRequirements(requiredPlugins, addedRequirements);

Set<BundleDescription> requirementsOfRequirements = DependencyManager.findRequirementsClosure(addedRequirements);
Set<String> rorIds = requirementsOfRequirements.stream().map(BundleDescription::getSymbolicName).collect(Collectors.toSet());
addAbsentRequirements(rorIds, null);
}

private void addAbsentRequirements(Collection<String> requirements, Set<BundleDescription> addedRequirements) throws CoreException {
for (String id : requirements) {
List<IPluginModelBase> models = fAllBundles.computeIfAbsent(id, k -> new ArrayList<>());
if (models.stream().noneMatch(m -> m.getBundleDescription().isResolved())) {
IPluginModelBase model = findRequiredPluginInTargetOrHost(id);
models.add(model);
BundleLauncherHelper.addDefaultStartingBundle(fModels, model);
if (addedRequirements != null) {
addedRequirements.add(model.getBundleDescription());
}
}
}
}

/**
* @noreference This method is not intended to be referenced by clients.
* @param configuration non null config
* @return required plugins
*/
@SuppressWarnings("restriction")
public static Collection<String> getRequiredJunitRuntimePlugins(ILaunchConfiguration configuration) {
org.eclipse.jdt.internal.junit.launcher.ITestKind testKind = org.eclipse.jdt.internal.junit.launcher.JUnitLaunchConfigurationConstants.getTestRunnerKind(configuration);
if (testKind.isNull()) {
return Collections.emptyList();
}
List<String> plugins = new ArrayList<>();
plugins.add("org.eclipse.pde.junit.runtime"); //$NON-NLS-1$

if (org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT4_TEST_KIND_ID.equals(testKind.getId())) {
plugins.add("org.eclipse.jdt.junit4.runtime"); //$NON-NLS-1$
} else if (org.eclipse.jdt.internal.junit.launcher.TestKindRegistry.JUNIT5_TEST_KIND_ID.equals(testKind.getId())) {
plugins.add("org.eclipse.jdt.junit5.runtime"); //$NON-NLS-1$
}
return plugins;
}

/**
* Checks for old-style plugin.xml files that have become stale since the last launch.
* For any stale plugin.xml files found, the corresponding MANIFEST.MF is deleted
Expand Down
9 changes: 0 additions & 9 deletions ui/org.eclipse.pde.ui/.settings/.api_filters
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,6 @@
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/pde/internal/ui/launcher/PluginBlock.java" type="org.eclipse.pde.internal.ui.launcher.PluginBlock">
<filter id="640712815">
<message_arguments>
<message_argument value="JUnitLaunchConfigurationDelegate"/>
<message_argument value="PluginBlock"/>
<message_argument value="getRequiredJunitRuntimePlugins(ILaunchConfiguration)"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/pde/internal/ui/refactoring/RenamePluginProcessor.java" type="org.eclipse.pde.internal.ui.refactoring.RenamePluginProcessor">
<filter id="572522506">
<message_arguments>
Expand Down
Loading
Loading