blob: 20bc490ece007e2da989ec811b9f49488d005db2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2019 Sonatype Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sonatype Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.core.maven.utils;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.internal.LifecyclePluginResolver;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MavenPluginManager;
import org.apache.maven.plugin.PluginDescriptorCache;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
/**
* Helper class that allows execution of components from maven plugin class realms. Normally, these
* components are not visible from tycho-core extensions plugin and require treatment. Typical usage
*
* <pre>
* &#64;Requirement
* private EquinoxServiceFactory equinox;
*
* &#64;Requirement
* private PluginRealmHelper pluginRealmHelper;
*
* ...
*
* public void someMethod(final MavenSession session, final MavenProject project) throws MavenExecutionException {
* pluginRealmHelper..execute(session, project, new Runnable() {
* public void run() {
* try {
* equinox.lookup(SomeComponent.class).someComponentMethod();
* } catch (ComponentLookupException e) {
* // have not found anything
* }
* }
* }, new PluginFilter() {
* public boolean accept(PluginDescriptor descriptor) {
* return true if the plugin is relevant;
* }
* });
* }
* </pre>
*
*/
@Component(role = PluginRealmHelper.class)
public class PluginRealmHelper {
public static interface PluginFilter {
public boolean accept(PluginDescriptor descriptor);
}
@Requirement
private Logger logger;
@Requirement
private MavenPluginManager pluginManager;
@Requirement
private BuildPluginManager buildPluginManager;
@Requirement
private PluginDescriptorCache pluginDescriptorCache;
@Requirement
private LifecyclePluginResolver lifecyclePluginResolver;
@Requirement
private MavenCompatiblityHelper compatibilityHelper;
public void execute(MavenSession session, MavenProject project, Runnable runnable, PluginFilter filter)
throws MavenExecutionException {
for (Plugin plugin : project.getBuildPlugins()) {
if (plugin.isExtensions()) {
// due to maven classloading model limitations, build extensions plugins cannot share classes
// since tycho core, i.e. this code, is loaded as a build extension, no other extensions plugin
// can load classes from tycho core
// https://cwiki.apache.org/MAVEN/maven-3x-class-loading.html
continue;
}
try {
lifecyclePluginResolver.resolveMissingPluginVersions(project, session);
PluginDescriptor pluginDescriptor;
try {
pluginDescriptor = compatibilityHelper.getPluginDescriptor(plugin, project, session);
} catch (PluginResolutionException e) {
// if the plugin really does not exist, the Maven build will fail later on anyway -> ignore for now (cf. bug #432957)
logger.debug("PluginResolutionException while looking for components from " + plugin, e);
continue;
}
if (pluginDescriptor != null) {
if (filter == null || filter.accept(pluginDescriptor)) {
ClassRealm pluginRealm;
MavenProject oldCurrentProject = session.getCurrentProject();
session.setCurrentProject(project);
try {
pluginRealm = buildPluginManager.getPluginRealm(session, pluginDescriptor);
} finally {
session.setCurrentProject(oldCurrentProject);
}
if (pluginRealm != null) {
ClassLoader origTCCL = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(pluginRealm);
runnable.run();
} finally {
Thread.currentThread().setContextClassLoader(origTCCL);
}
}
}
}
} catch (PluginManagerException | PluginResolutionException | PluginVersionResolutionException
| PluginDescriptorParsingException | InvalidPluginDescriptorException e) {
throw newMavenExecutionException(e);
}
}
}
private static MavenExecutionException newMavenExecutionException(Exception cause) {
return new MavenExecutionException("Could not setup plugin ClassRealm", cause);
}
}