diff --git a/.gitmodules b/.gitmodules index d38c67bf7e..5e9e19f526 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "m2e-core-tests"] path = m2e-core-tests - url = https://github.com/tesla/m2e-core-tests.git - branch = master + url = https://github.com/HannesWell/m2e-core-tests.git + branch = serviceUtilities diff --git a/m2e-core-tests b/m2e-core-tests index d74ab38782..fe3470d80e 160000 --- a/m2e-core-tests +++ b/m2e-core-tests @@ -1 +1 @@ -Subproject commit d74ab38782bf89dc31ca7390aaddb2f5b6010bea +Subproject commit fe3470d80ec6289ae270a394a1d51ceaec8ab76b diff --git a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/MavenBugsTest.java b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/MavenBugsTest.java index 3823a3d1a1..8ba578dc30 100644 --- a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/MavenBugsTest.java +++ b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/MavenBugsTest.java @@ -26,7 +26,8 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.NullProgressMonitor; -import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.M2EUtils; +import org.eclipse.m2e.core.internal.project.registry.MavenProjectManager; import org.eclipse.m2e.core.project.IMavenProjectFacade; import org.eclipse.m2e.core.project.MavenProjectInfo; import org.eclipse.m2e.core.project.ProjectImportConfiguration; @@ -86,8 +87,8 @@ public void testMNG6530() throws Exception { public void testMultiModuleProjectDirectoryChild() throws Exception { IProject project = createExisting("simple", "resources/projects/dotMvn/", false); waitForJobsToComplete(monitor); - IMavenProjectFacade facade = MavenPluginActivator.getDefault().getMavenProjectManagerImpl().create(project.getFile("child/pom.xml"), - true, monitor); + IMavenProjectFacade facade = M2EUtils.useService(MavenProjectManager.class, + m -> m.create(project.getFile("child/pom.xml"), true, monitor)); Assert.assertNotNull(facade); File[] multiModuleDirectory = new File[] { null }; facade.createExecutionContext().execute((context, monitor) -> multiModuleDirectory[0] = context.getExecutionRequest().getMultiModuleProjectDirectory(), null); diff --git a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/RegistryTest.java b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/RegistryTest.java index eac589a920..0863cda56a 100644 --- a/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/RegistryTest.java +++ b/org.eclipse.m2e.core.tests/src/org/eclipse/m2e/core/internal/project/registry/RegistryTest.java @@ -23,6 +23,8 @@ import java.util.Collections; import java.util.Optional; +import javax.inject.Inject; + import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; @@ -31,31 +33,38 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.m2e.core.embedder.ArtifactKey; -import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.M2EUtils; import org.eclipse.m2e.core.project.IMavenProjectFacade; import org.eclipse.m2e.core.project.MavenUpdateRequest; import org.eclipse.m2e.core.project.ProjectImportConfiguration; import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase; +import org.eclipse.m2e.tests.common.OSGiServiceInjector; import org.junit.Assert; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; public class RegistryTest extends AbstractMavenProjectTestCase { + @Rule + public OSGiServiceInjector serviceInjector = OSGiServiceInjector.INSTANCE; + + @Inject + private ProjectRegistryManager projectRegistryManager; + @Test public void testDeletedFacadeIsRemoved() throws IOException, CoreException, InterruptedException { IProject project = createExisting(getClass().getSimpleName(), "resources/projects/simplePomOK", true); waitForJobsToComplete(monitor); - IMavenProjectFacade facade = MavenPluginActivator.getDefault().getMavenProjectManagerImpl().create(project, - monitor); + IMavenProjectFacade facade = projectRegistryManager.create(project, monitor); Assert.assertNotNull(facade); project.delete(true, monitor); waitForJobsToComplete(new NullProgressMonitor()); Assert.assertTrue(facade.isStale()); project = createExisting(getClass().getSimpleName(), "resources/projects/emptyPom", true); waitForJobsToComplete(monitor); - facade = MavenPluginActivator.getDefault().getMavenProjectManagerImpl().create(project, monitor); + facade = projectRegistryManager.create(project, monitor); Assert.assertNull(facade); } @@ -63,8 +72,7 @@ public void testDeletedFacadeIsRemoved() throws IOException, CoreException, Inte public void testMissingParentCapabilityStored() throws IOException, CoreException, InterruptedException { IProject project = createExisting(getClass().getSimpleName(), "resources/projects/missingParent", true); waitForJobsToComplete(monitor); - MutableProjectRegistry registry = MavenPluginActivator.getDefault().getMavenProjectManagerImpl() - .newMutableProjectRegistry(); + MutableProjectRegistry registry = projectRegistryManager.newMutableProjectRegistry(); MavenCapability parentCapability = MavenCapability .createMavenParent(new ArtifactKey("missingGroup", "missingArtifactId", "1", null)); assertEquals(Collections.singleton(project.getFile("pom.xml")), registry.getDependents(parentCapability, false)); @@ -75,14 +83,13 @@ public void testMultiRefreshKeepsCapabilities() throws IOException, CoreExceptio IProject dependentProject = createExisting("dependent", "resources/projects/dependency/dependent", true); IProject dependencyProject = createExisting("dependency", "resources/projects/dependency/dependency", true); waitForJobsToComplete(monitor); - ProjectRegistryManager registryManager = MavenPluginActivator.getDefault().getMavenProjectManagerImpl(); - Collection pomFiles = new ArrayList<>(2); + Collection pomFiles = new ArrayList<>(2); pomFiles.add(dependentProject.getFile("pom.xml")); pomFiles.add(dependencyProject.getFile("pom.xml")); - MutableProjectRegistry state = MavenPluginActivator.getDefault().getMavenProjectManagerImpl().newMutableProjectRegistry(); + MutableProjectRegistry state = projectRegistryManager.newMutableProjectRegistry(); state.clear(); - registryManager.getMaven().execute(false, false, (context, aMonitor) -> { - registryManager.refresh(state, pomFiles, aMonitor); + projectRegistryManager.getMaven().execute(false, false, (context, aMonitor) -> { + projectRegistryManager.refresh(state, pomFiles, aMonitor); return null; }, monitor); Assert.assertNotEquals(Collections.emptyMap(), state.requiredCapabilities); @@ -115,7 +122,9 @@ public void testResolvedParentConfiguration() throws Exception { request.addPomFile(parent.getFile("pom.xml")); IFile childPom = child.getFile("pom.xml"); request.addPomFile(childPom); - MavenPluginActivator.getDefault().getProjectManagerRefreshJob().refresh(request); + try (var refreshJob = M2EUtils.useService(ProjectRegistryRefreshJob.class)) { + refreshJob.get().refresh(request); + } waitForJobsToComplete(); IMarker[] markers = childPom.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); assertArrayEquals(new IMarker[0], markers); diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/launch/MavenInstallationsPreferencePage.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/launch/MavenInstallationsPreferencePage.java index d6f91a7b00..1591fee900 100644 --- a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/launch/MavenInstallationsPreferencePage.java +++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/preferences/launch/MavenInstallationsPreferencePage.java @@ -48,7 +48,8 @@ import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.embedder.IMaven; import org.eclipse.m2e.core.embedder.IMavenConfiguration; -import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.M2EUtils; +import org.eclipse.m2e.core.internal.M2EUtils.ServiceUsage; import org.eclipse.m2e.core.internal.launch.AbstractMavenRuntime; import org.eclipse.m2e.core.internal.launch.MavenRuntimeManagerImpl; import org.eclipse.m2e.core.ui.internal.Messages; @@ -62,6 +63,8 @@ @SuppressWarnings("restriction") public class MavenInstallationsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { + final ServiceUsage runtimeManagerUsage; + final MavenRuntimeManagerImpl runtimeManager; final IMavenConfiguration mavenConfiguration; @@ -76,8 +79,8 @@ public class MavenInstallationsPreferencePage extends PreferencePage implements public MavenInstallationsPreferencePage() { setTitle(Messages.MavenInstallationsPreferencePage_title); - - this.runtimeManager = MavenPluginActivator.getDefault().getMavenRuntimeManager(); + this.runtimeManagerUsage = M2EUtils.useService(MavenRuntimeManagerImpl.class); + this.runtimeManager = runtimeManagerUsage.get(); this.mavenConfiguration = MavenPlugin.getMavenConfiguration(); this.maven = MavenPlugin.getMaven(); } @@ -105,6 +108,12 @@ public boolean performOk() { return true; } + @Override + public void dispose() { + runtimeManagerUsage.close(); + super.dispose(); + } + @Override protected Control createContents(Composite parent) { diff --git a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java index 6360e4627c..639b746672 100644 --- a/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java +++ b/org.eclipse.m2e.core.ui/src/org/eclipse/m2e/core/ui/internal/wizards/MavenPomSelectionComponent.java @@ -64,7 +64,7 @@ import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.embedder.ArtifactKey; import org.eclipse.m2e.core.internal.IMavenConstants; -import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.M2EUtils; import org.eclipse.m2e.core.internal.index.IIndex; import org.eclipse.m2e.core.internal.index.IndexedArtifact; import org.eclipse.m2e.core.internal.index.IndexedArtifactFile; @@ -256,14 +256,14 @@ public void init(String queryText, String queryType, IProject project, Set files = getSelectedIndexedArtifactFiles(selection); - ArtifactFilterManager filterManager = MavenPluginActivator.getDefault().getArifactFilterManager(); - - for(IndexedArtifactFile file : files) { - ArtifactKey key = file.getAdapter(ArtifactKey.class); - IStatus status = filterManager.filter(MavenPomSelectionComponent.this.project, key); - if(!status.isOK()) { - setStatus(IStatus.ERROR, status.getMessage()); - return; // TODO not nice to exit method like this + try (var filterManager = M2EUtils.useService(ArtifactFilterManager.class)) { + for(IndexedArtifactFile file : files) { + ArtifactKey key = file.getAdapter(ArtifactKey.class); + IStatus status = filterManager.get().filter(MavenPomSelectionComponent.this.project, key); + if(!status.isOK()) { + setStatus(IStatus.ERROR, status.getMessage()); + return; // TODO not nice to exit method like this + } } } diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/M2EUtils.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/M2EUtils.java index 31b6407d31..c595988221 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/M2EUtils.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/M2EUtils.java @@ -14,12 +14,20 @@ package org.eclipse.m2e.core.internal; import java.io.File; +import java.lang.StackWalker.Option; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.HashSet; +import java.util.NoSuchElementException; import java.util.Properties; import java.util.Set; import java.util.Stack; +import java.util.function.Function; +import java.util.function.Supplier; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -170,4 +178,73 @@ public static void copyProperties(Properties to, Properties from) { } } } + + public interface ServiceUsage extends AutoCloseable, Supplier { + @Override + void close(); // do not throw checked exception + + boolean isAvailable(); + } + + private static final StackWalker WALKER = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE); + + public static ServiceUsage useService(Class serviceClass) { + Class callerClass = WALKER.getCallerClass(); + BundleContext ctx = FrameworkUtil.getBundle(callerClass).getBundleContext(); + return useService(serviceClass, ctx); + } + + public static R useService(Class serviceClass, Function function) { + Class callerClass = WALKER.getCallerClass(); + BundleContext ctx = FrameworkUtil.getBundle(callerClass).getBundleContext(); + try (var service = useService(serviceClass, ctx)) { + return function.apply(service.get()); + } + } + + private static ServiceUsage useService(Class serviceClass, BundleContext ctx) { + ServiceReference reference = ctx != null ? ctx.getServiceReference(serviceClass) : null; + return useService(serviceClass, reference, ctx); + } + + private static ServiceUsage useService(Class serviceClass, ServiceReference reference, + BundleContext ctx) { + T service = reference != null ? ctx.getService(reference) : null; + return service == null ? getUnavailableServiceUsage(serviceClass.getName()) : new ServiceUsage<>() { + @Override + public T get() { + return service; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public void close() { + ctx.ungetService(reference); + } + }; + } + + private static ServiceUsage getUnavailableServiceUsage(String serviceName) { + return new ServiceUsage<>() { + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public T get() { + throw new NoSuchElementException("Service '" + serviceName + "' is not available"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + @Override + public void close() { // nothing to do + } + }; + } + } diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java index 7829b93a11..019332b26c 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java @@ -59,12 +59,9 @@ import org.eclipse.m2e.core.embedder.MavenModelManager; import org.eclipse.m2e.core.internal.archetype.ArchetypeCatalogFactory; import org.eclipse.m2e.core.internal.archetype.ArchetypeManager; -import org.eclipse.m2e.core.internal.index.filter.ArtifactFilterManager; -import org.eclipse.m2e.core.internal.launch.MavenRuntimeManagerImpl; import org.eclipse.m2e.core.internal.lifecyclemapping.LifecycleMappingFactory; import org.eclipse.m2e.core.internal.markers.IMavenMarkerManager; import org.eclipse.m2e.core.internal.project.registry.ProjectRegistryManager; -import org.eclipse.m2e.core.internal.project.registry.ProjectRegistryRefreshJob; import org.eclipse.m2e.core.project.IMavenProjectRegistry; import org.eclipse.m2e.core.project.IProjectConfigurationManager; import org.eclipse.m2e.core.project.IWorkspaceClassifierResolverManager; @@ -217,10 +214,6 @@ public ProjectRegistryManager getMavenProjectManagerImpl() { return getService(ProjectRegistryManager.class); } - public MavenRuntimeManagerImpl getMavenRuntimeManager() { - return getService(MavenRuntimeManagerImpl.class); - } - public ArchetypeManager getArchetypeManager() { synchronized(this) { if(this.archetypeManager == null) { @@ -258,11 +251,6 @@ public IProjectConfigurationManager getProjectConfigurationManager() { return getService(IProjectConfigurationManager.class); } - /** for use by unit tests */ - public ProjectRegistryRefreshJob getProjectManagerRefreshJob() { - return getService(ProjectRegistryRefreshJob.class); - } - public static String getVersion() { return plugin.version; } @@ -283,10 +271,6 @@ public RepositorySystem getRepositorySystem() throws CoreException { return getMaven().lookup(RepositorySystem.class); } - public ArtifactFilterManager getArifactFilterManager() { - return getService(ArtifactFilterManager.class); - } - /** * @return */ diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java index 36f0018b48..1d04e3bec9 100644 --- a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java +++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchUtils.java @@ -27,7 +27,7 @@ import org.eclipse.m2e.actions.MavenLaunchConstants; import org.eclipse.m2e.core.internal.Bundles; -import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.M2EUtils; import org.eclipse.m2e.core.internal.launch.AbstractMavenRuntime; import org.eclipse.m2e.core.internal.launch.MavenRuntimeManagerImpl; import org.eclipse.m2e.workspace.WorkspaceState; @@ -44,9 +44,8 @@ private MavenLaunchUtils() { // static use only } public static AbstractMavenRuntime getMavenRuntime(ILaunchConfiguration configuration) throws CoreException { - MavenRuntimeManagerImpl runtimeManager = MavenPluginActivator.getDefault().getMavenRuntimeManager(); String name = configuration.getAttribute(MavenLaunchConstants.ATTR_RUNTIME, ""); //$NON-NLS-1$ - AbstractMavenRuntime runtime = runtimeManager.getRuntime(name); + AbstractMavenRuntime runtime = M2EUtils.useService(MavenRuntimeManagerImpl.class, rm -> rm.getRuntime(name)); if(runtime == null) { throw new CoreException(new Status(IStatus.ERROR, MavenLaunchConstants.PLUGIN_ID, -1, // NLS.bind(Messages.MavenLaunchUtils_error_no_maven_install, name), null)); diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/ui/internal/launch/MavenRuntimeSelector.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/ui/internal/launch/MavenRuntimeSelector.java index 514f4d1c71..69a78d04b6 100644 --- a/org.eclipse.m2e.launching/src/org/eclipse/m2e/ui/internal/launch/MavenRuntimeSelector.java +++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/ui/internal/launch/MavenRuntimeSelector.java @@ -38,7 +38,7 @@ import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.m2e.actions.MavenLaunchConstants; -import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.eclipse.m2e.core.internal.M2EUtils; import org.eclipse.m2e.core.internal.launch.AbstractMavenRuntime; import org.eclipse.m2e.core.internal.launch.MavenEmbeddedRuntime; import org.eclipse.m2e.core.internal.launch.MavenExternalRuntime; @@ -55,10 +55,6 @@ public class MavenRuntimeSelector extends Composite { private Button configureRuntimesButton; - private static MavenRuntimeManagerImpl getRuntimeManager() { - return MavenPluginActivator.getDefault().getMavenRuntimeManager(); - } - public MavenRuntimeSelector(final Composite mainComposite) { super(mainComposite, SWT.BACKGROUND); mainComposite.setBackgroundMode(SWT.INHERIT_DEFAULT); @@ -150,10 +146,11 @@ protected String getType(AbstractMavenRuntime runtime) { } protected void setInput() { - MavenRuntimeManagerImpl runtimeManager = getRuntimeManager(); - runtimeComboViewer.setInput(runtimeManager.getMavenRuntimes()); - runtimeComboViewer - .setSelection(new StructuredSelection(runtimeManager.getRuntime(MavenRuntimeManagerImpl.DEFAULT))); + try (var runtimeManager = M2EUtils.useService(MavenRuntimeManagerImpl.class)) { + runtimeComboViewer.setInput(runtimeManager.get().getMavenRuntimes()); + runtimeComboViewer + .setSelection(new StructuredSelection(runtimeManager.get().getRuntime(MavenRuntimeManagerImpl.DEFAULT))); + } } public void setSelectRuntime(AbstractMavenRuntime runtime) { @@ -170,16 +167,15 @@ public void addSelectionChangedListener(ISelectionChangedListener listener) { } public void initializeFrom(ILaunchConfiguration configuration) { - String name = ""; - try { - name = configuration.getAttribute(MavenLaunchConstants.ATTR_RUNTIME, ""); //$NON-NLS-1$ + try (var runtimeManager = M2EUtils.useService(MavenRuntimeManagerImpl.class)) { + String name = configuration.getAttribute(MavenLaunchConstants.ATTR_RUNTIME, ""); //$NON-NLS-1$ + AbstractMavenRuntime runtime = runtimeManager.get().getRuntime(name); + if(runtime != null) { + setSelectRuntime(runtime); + } } catch(CoreException ex) { // TODO log } - AbstractMavenRuntime runtime = getRuntimeManager().getRuntime(name); - if(runtime != null) { - setSelectRuntime(runtime); - } } public void performApply(ILaunchConfigurationWorkingCopy configuration) { diff --git a/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF b/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF index fa2df772b9..efd6b9472f 100644 --- a/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF +++ b/org.eclipse.m2e.pde.connector/META-INF/MANIFEST.MF @@ -14,4 +14,3 @@ Require-Bundle: org.eclipse.m2e.core;bundle-version="1.18.4", org.eclipse.m2e.maven.runtime;bundle-version="1.18.1", org.eclipse.pde.core, org.eclipse.jdt.core -Bundle-Activator: org.eclipse.m2e.pde.connector.Activator diff --git a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/Activator.java b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/Activator.java deleted file mode 100644 index 0a49a4ced5..0000000000 --- a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/Activator.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2021 Christoph Läubrich - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-v20.html - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Christoph Läubrich - initial API and implementation - *******************************************************************************/ -package org.eclipse.m2e.pde.connector; - -import java.util.Optional; - -import org.eclipse.pde.core.project.IBundleProjectService; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.util.tracker.ServiceTracker; - -public class Activator implements BundleActivator { - - private static volatile ServiceTracker bundleProjectServiceTracker; - - @Override - public void start(BundleContext context) throws Exception { - bundleProjectServiceTracker = new ServiceTracker<>(context, IBundleProjectService.class, null); - bundleProjectServiceTracker.open(); - } - - @Override - public void stop(BundleContext context) throws Exception { - bundleProjectServiceTracker.close(); - } - - public static Optional getBundleProjectService() { - if (bundleProjectServiceTracker == null) { - return Optional.empty(); - } - return Optional.ofNullable(bundleProjectServiceTracker.getService()); - } - -} diff --git a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java index 4af089052c..4a036c97b0 100644 --- a/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java +++ b/org.eclipse.m2e.pde.connector/src/org/eclipse/m2e/pde/connector/PDEProjectHelper.java @@ -31,6 +31,7 @@ import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; +import org.eclipse.m2e.core.internal.M2EUtils; import org.eclipse.m2e.core.project.MavenProjectUtils; import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator; import org.eclipse.pde.core.plugin.IPluginModelBase; @@ -150,14 +151,15 @@ public static void addPDENature(IProject project, IPath manifestPath, IProgressM protected static void setManifestLocaton(IProject project, IPath manifestPath, IProgressMonitor monitor) throws CoreException { - IBundleProjectService projectService = Activator.getBundleProjectService().get(); - if (manifestPath != null && manifestPath.segmentCount() > 1) { - IPath metainfPath = manifestPath.removeLastSegments(1); - project.getFile(metainfPath).refreshLocal(IResource.DEPTH_INFINITE, monitor); - projectService.setBundleRoot(project, metainfPath); - } else { - // in case of configuration update, reset to the default value - projectService.setBundleRoot(project, null); + try (var projectService = M2EUtils.useService(IBundleProjectService.class)) { + if (manifestPath != null && manifestPath.segmentCount() > 1) { + IPath metainfPath = manifestPath.removeLastSegments(1); + project.getFile(metainfPath).refreshLocal(IResource.DEPTH_INFINITE, monitor); + projectService.get().setBundleRoot(project, metainfPath); + } else { + // in case of configuration update, reset to the default value + projectService.get().setBundleRoot(project, null); + } } } diff --git a/org.eclipse.m2e.profiles.core.tests/META-INF/MANIFEST.MF b/org.eclipse.m2e.profiles.core.tests/META-INF/MANIFEST.MF index fbba870960..e95b188680 100644 --- a/org.eclipse.m2e.profiles.core.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.m2e.profiles.core.tests/META-INF/MANIFEST.MF @@ -8,9 +8,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-11 Bundle-Vendor: Eclipse.org - m2e Require-Bundle: org.eclipse.m2e.tests.common;bundle-version="1.16.0", org.junit;bundle-version="4.12.0", - org.eclipse.core.resources, - org.eclipse.core.runtime, - org.eclipse.m2e.maven.runtime;bundle-version="1.10.0" -Import-Package: javax.annotation;version="1.2.0" + org.eclipse.core.resources +Import-Package: javax.inject;version="1.0.0" Eclipse-BundleShape: dir Automatic-Module-Name: org.eclipse.m2e.profiles.core.tests diff --git a/org.eclipse.m2e.profiles.core.tests/src/org/eclipse/m2e/profiles/core/internal/management/MavenProfileManagerTest.java b/org.eclipse.m2e.profiles.core.tests/src/org/eclipse/m2e/profiles/core/internal/management/MavenProfileManagerTest.java index 089f415199..bc6cf945ff 100644 --- a/org.eclipse.m2e.profiles.core.tests/src/org/eclipse/m2e/profiles/core/internal/management/MavenProfileManagerTest.java +++ b/org.eclipse.m2e.profiles.core.tests/src/org/eclipse/m2e/profiles/core/internal/management/MavenProfileManagerTest.java @@ -22,6 +22,8 @@ import java.util.Set; import java.util.stream.Collectors; +import javax.inject.Inject; + import org.eclipse.core.resources.IProject; import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.internal.IMavenConstants; @@ -29,31 +31,18 @@ import org.eclipse.m2e.profiles.core.internal.IProfileManager; import org.eclipse.m2e.profiles.core.internal.ProfileData; import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.eclipse.m2e.tests.common.OSGiServiceInjector; +import org.junit.Rule; import org.junit.Test; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.FrameworkUtil; -import org.osgi.util.tracker.ServiceTracker; - @SuppressWarnings("restriction") public class MavenProfileManagerTest extends AbstractMavenProjectTestCase { - private static ServiceTracker profileManagerTracker; - - @BeforeClass - public static void setUpProfileManagerTracker() throws BundleException { - BundleContext context = FrameworkUtil.getBundle(MavenProfileManagerTest.class).getBundleContext(); - profileManagerTracker = new ServiceTracker<>(context, IProfileManager.class, null); - profileManagerTracker.open(); - } + @Rule + public OSGiServiceInjector serviceInjector = OSGiServiceInjector.INSTANCE; - @AfterClass - public static void tearDownProfileManagerTracker() { - profileManagerTracker.close(); - } + @Inject + public IProfileManager profileManager; @Test public void testLoadingProfilesFromPomsResolvedViaTheirRelativePath() throws Exception { @@ -70,7 +59,7 @@ public void testLoadingProfilesFromPomsResolvedViaTheirRelativePath() throws Exc // -- When... // - List profiles = profileManagerTracker.getService().getProfileDatas(facade, monitor); + List profiles = profileManager.getProfileDatas(facade, monitor); // -- Then... // diff --git a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/ProfileSelectionHandler.java b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/ProfileSelectionHandler.java index cde5391cbd..fb6e69f618 100644 --- a/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/ProfileSelectionHandler.java +++ b/org.eclipse.m2e.profiles.ui/src/org/eclipse/m2e/profiles/ui/internal/actions/ProfileSelectionHandler.java @@ -22,10 +22,6 @@ import java.util.Map; import java.util.Set; -import javax.inject.Inject; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,9 +42,6 @@ import org.eclipse.core.runtime.jobs.IJobChangeListener; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.JobChangeAdapter; -import org.eclipse.e4.core.contexts.ContextInjectionFactory; -import org.eclipse.e4.core.contexts.EclipseContextFactory; -import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.window.Window; @@ -59,6 +52,7 @@ import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.internal.M2EUtils; import org.eclipse.m2e.core.project.IMavenProjectFacade; import org.eclipse.m2e.profiles.core.internal.IProfileManager; import org.eclipse.m2e.profiles.core.internal.ProfileData; @@ -78,15 +72,6 @@ public class ProfileSelectionHandler extends AbstractHandler { private static final Logger log = LoggerFactory.getLogger(ProfileSelectionHandler.class); - @Inject - private IProfileManager profileManager; - - public ProfileSelectionHandler() { - BundleContext context = FrameworkUtil.getBundle(ProfileSelectionHandler.class).getBundleContext(); - IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(context); - ContextInjectionFactory.inject(this, serviceContext); - } - /** * Opens the Maven profile selection Dialog window. */ @@ -117,15 +102,15 @@ public IStatus execute(Shell shell, IProject... projects) { display(shell, Messages.ProfileSelectionHandler_Select_some_maven_projects); return null; } - GetProfilesJob getProfilesJob = new GetProfilesJob(facades, profileManager); - getProfilesJob.addJobChangeListener(onProfilesFetched(getProfilesJob, facades, profileManager, shell)); + GetProfilesJob getProfilesJob = new GetProfilesJob(facades); + getProfilesJob.addJobChangeListener(onProfilesFetched(getProfilesJob, facades, shell)); getProfilesJob.setUser(true); getProfilesJob.schedule(); return Status.OK_STATUS; } - private IJobChangeListener onProfilesFetched(final GetProfilesJob getProfilesJob, - final Set facades, final IProfileManager profileManager, final Shell shell) { + private IJobChangeListener onProfilesFetched(GetProfilesJob getProfilesJob, Set facades, + Shell shell) { return new JobChangeAdapter() { @@ -137,7 +122,7 @@ public void done(IJobChangeEvent event) { Map> allProfiles = getProfilesJob.getAllProfiles(); final SelectProfilesDialog dialog = new SelectProfilesDialog(shell, facades, sharedProfiles); if(dialog.open() == Window.OK) { - Job job = new UpdateProfilesJob(allProfiles, sharedProfiles, profileManager, dialog); + Job job = new UpdateProfilesJob(allProfiles, sharedProfiles, dialog); job.setRule(MavenPlugin.getProjectConfigurationManager().getRule()); job.schedule(); } @@ -182,24 +167,21 @@ private Set getMavenProjects(IProject[] projects) { class GetProfilesJob extends Job { - private final IProfileManager profileManager; - private final Set facades; private Map> allProfiles; private List sharedProfiles; - private GetProfilesJob(final Set facades, IProfileManager profileManager) { + private GetProfilesJob(final Set facades) { super(Messages.ProfileSelectionHandler_Loading_maven_profiles); this.facades = facades; - this.profileManager = profileManager; } @Override protected IStatus run(IProgressMonitor monitor) { - try { - this.allProfiles = getAllProfiles(facades, profileManager); + try (var profileManager = M2EUtils.useService(IProfileManager.class)) { + this.allProfiles = getAllProfiles(facades, profileManager.get()); this.sharedProfiles = getSharedProfiles(allProfiles); } catch(CoreException e) { return Status.error(Messages.ProfileSelectionHandler_Unable_to_open_profile_dialog, e); @@ -303,21 +285,18 @@ class UpdateProfilesJob extends WorkspaceJob { private final List sharedProfiles; - private final IProfileManager profileManager; - private final SelectProfilesDialog dialog; private UpdateProfilesJob(Map> allProfiles, - List sharedProfiles, IProfileManager profileManager, SelectProfilesDialog dialog) { + List sharedProfiles, SelectProfilesDialog dialog) { super(Messages.ProfileManager_Updating_maven_profiles); this.allProfiles = allProfiles; this.sharedProfiles = sharedProfiles; - this.profileManager = profileManager; this.dialog = dialog; } public IStatus runInWorkspace(IProgressMonitor monitor) { - try { + try (var profileManager = M2EUtils.useService(IProfileManager.class)) { SubMonitor progress = SubMonitor.convert(monitor, Messages.ProfileManager_Updating_maven_profiles, 100); SubMonitor subProgress = SubMonitor.convert(progress.newChild(5), allProfiles.size() * 100); for(Map.Entry> entry : allProfiles.entrySet()) { @@ -327,7 +306,7 @@ public IStatus runInWorkspace(IProgressMonitor monitor) { IMavenProjectFacade facade = entry.getKey(); List activeProfiles = getActiveProfiles(sharedProfiles, entry.getValue()); - profileManager.updateActiveProfiles(facade, activeProfiles, dialog.isOffline(), dialog.isForceUpdate(), + profileManager.get().updateActiveProfiles(facade, activeProfiles, dialog.isOffline(), dialog.isForceUpdate(), subProgress.newChild(100)); } } catch(CoreException ex) { diff --git a/org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF b/org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF index 3ae3b628ee..2392062c43 100644 --- a/org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF +++ b/org.eclipse.m2e.tests.common/META-INF/MANIFEST.MF @@ -7,22 +7,22 @@ Require-Bundle: org.junit;bundle-version="4.0.0", org.eclipse.m2e.core;bundle-version="1.16.0", org.eclipse.m2e.maven.runtime;bundle-version="1.16.0", org.eclipse.m2e.jdt;bundle-version="1.16.0", - org.eclipse.m2e.lifecyclemapping.defaults;bundle-version="1.16.0", org.eclipse.core.runtime, org.eclipse.jdt.core, org.eclipse.debug.core, - org.eclipse.core.resources, org.eclipse.jetty.server, org.eclipse.jetty.util, org.eclipse.jetty.http, org.eclipse.jetty.security, - org.eclipse.jetty.io + org.apache.felix.scr Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-11 Bundle-Vendor: Eclipse.org - m2e MavenArtifact-GroupId: org.eclipse.m2e MavenArtifact-ArtifactId: org.eclipse.m2e.tests.common Export-Package: org.eclipse.m2e.tests.common;x-friends:="org.eclipse.m2e.tests,org.eclipse.m2e.core.tests,org.eclipse.m2e.jdt.tests,org.eclipse.m2e.core.ui.tests" -Import-Package: javax.servlet;version="3.1.0", - javax.servlet.http;version="3.1.0" +Import-Package: javax.inject;version="1.0.0", + javax.servlet.http;version="3.1.0", + org.eclipse.e4.core.contexts;version="1.7.0", + org.eclipse.e4.core.di;version="1.7.0" Automatic-Module-Name: org.eclipse.m2e.tests.common diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java index 0febd05564..e77f3773bd 100644 --- a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java +++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/AbstractMavenProjectTestCase.java @@ -35,6 +35,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.inject.Inject; + import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -105,11 +107,15 @@ public abstract class AbstractMavenProjectTestCase { protected IWorkspace workspace; + @Rule + public OSGiServiceInjector serviceInjector = OSGiServiceInjector.INSTANCE; + @Rule public TestName name = new TestName(); protected File repo; + @Inject protected ProjectRegistryRefreshJob projectRefreshJob; protected Job downloadSourcesJob; @@ -130,7 +136,6 @@ public void setUp() throws Exception { options.put(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ".svn/"); JavaCore.setOptions(options); - projectRefreshJob = MavenPluginActivator.getDefault().getProjectManagerRefreshJob(); projectRefreshJob.sleep(); downloadSourcesJob = ((BuildPathManager) MavenJdtPlugin.getDefault().getBuildpathManager()).getDownloadSourcesJob(); diff --git a/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/OSGiServiceInjector.java b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/OSGiServiceInjector.java new file mode 100644 index 0000000000..91ae12d288 --- /dev/null +++ b/org.eclipse.m2e.tests.common/src/org/eclipse/m2e/tests/common/OSGiServiceInjector.java @@ -0,0 +1,49 @@ + +package org.eclipse.m2e.tests.common; + +import org.junit.rules.MethodRule; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.Statement; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +import org.eclipse.e4.core.contexts.ContextInjectionFactory; +import org.eclipse.e4.core.contexts.EclipseContextFactory; +import org.eclipse.e4.core.contexts.IEclipseContext; + + +public class OSGiServiceInjector implements MethodRule { + @SuppressWarnings("unused") // ensure the felix.scr participates in the launch to enable OSGi DS + private static org.apache.felix.scr.info.ScrInfo info; + + public static final OSGiServiceInjector INSTANCE = new OSGiServiceInjector(); + + private OSGiServiceInjector() { + } + + public @interface InjectService { + } + + @Override + public Statement apply(Statement base, FrameworkMethod method, Object target) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Bundle bundle = FrameworkUtil.getBundle(target.getClass()); + BundleContext context = bundle.getBundleContext(); + if(context == null) { + throw new IllegalStateException("Test bundle <" + bundle.getSymbolicName() + "> not started"); + } + // TODO: BundleContextOSGi ungets services immediately! + // 'Manually' search for fields to inject and set them via reflection + // and use a map of service trackers like in the m2e.core activator? + // Close the trackers after evaluation + IEclipseContext serviceContext = EclipseContextFactory.getServiceContext(context); + ContextInjectionFactory.inject(target, serviceContext); + + base.evaluate(); + } + }; + } +}