Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ServiceUsage utility and OSGiServiceInjector test-rule #726

Closed
wants to merge 1 commit into from
Closed
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
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,40 +33,46 @@
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);
}

@Test
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));
Expand All @@ -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<IFile> pomFiles = new ArrayList<>(2);
Collection<IFile> 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);
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -62,6 +63,8 @@
@SuppressWarnings("restriction")
public class MavenInstallationsPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

final ServiceUsage<MavenRuntimeManagerImpl> runtimeManagerUsage;

final MavenRuntimeManagerImpl runtimeManager;

final IMavenConfiguration mavenConfiguration;
Expand All @@ -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();
}
Expand Down Expand Up @@ -105,6 +108,12 @@ public boolean performOk() {
return true;
}

@Override
public void dispose() {
runtimeManagerUsage.close();
super.dispose();
}

@Override
protected Control createContents(Composite parent) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -256,14 +256,14 @@ public void init(String queryText, String queryType, IProject project, Set<Artif
if(!selection.isEmpty()) {
List<IndexedArtifactFile> 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
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -170,4 +178,73 @@ public static void copyProperties(Properties to, Properties from) {
}
}
}

public interface ServiceUsage<T> extends AutoCloseable, Supplier<T> {
@Override
void close(); // do not throw checked exception

boolean isAvailable();
}

private static final StackWalker WALKER = StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE);

public static <T> ServiceUsage<T> useService(Class<T> serviceClass) {
Class<?> callerClass = WALKER.getCallerClass();
BundleContext ctx = FrameworkUtil.getBundle(callerClass).getBundleContext();
return useService(serviceClass, ctx);
}

public static <T, R> R useService(Class<T> serviceClass, Function<T, R> function) {
Class<?> callerClass = WALKER.getCallerClass();
BundleContext ctx = FrameworkUtil.getBundle(callerClass).getBundleContext();
try (var service = useService(serviceClass, ctx)) {
return function.apply(service.get());
}
}

private static <T> ServiceUsage<T> useService(Class<T> serviceClass, BundleContext ctx) {
ServiceReference<T> reference = ctx != null ? ctx.getServiceReference(serviceClass) : null;
return useService(serviceClass, reference, ctx);
}

private static <T> ServiceUsage<T> useService(Class<T> serviceClass, ServiceReference<T> 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 <T> ServiceUsage<T> 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
}
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand All @@ -283,10 +271,6 @@ public RepositorySystem getRepositorySystem() throws CoreException {
return getMaven().lookup(RepositorySystem.class);
}

public ArtifactFilterManager getArifactFilterManager() {
return getService(ArtifactFilterManager.class);
}

/**
* @return
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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));
Expand Down
Loading