| /******************************************************************************* |
| * Copyright (c) 2015 Takari, Inc. |
| * All rights reserved. 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: |
| * Anton Tanasenko - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.m2e.editor.xml.internal.mojo; |
| |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.Callable; |
| import java.util.concurrent.ExecutionException; |
| |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.cache.Cache; |
| import com.google.common.cache.CacheBuilder; |
| import com.google.common.collect.ImmutableMap; |
| |
| import org.eclipse.aether.repository.RemoteRepository; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtension; |
| import org.eclipse.core.runtime.IExtensionPoint; |
| import org.eclipse.core.runtime.IExtensionRegistry; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.jface.operation.IRunnableWithProgress; |
| import org.eclipse.ui.PlatformUI; |
| |
| import org.codehaus.plexus.component.repository.exception.ComponentLookupException; |
| |
| import org.apache.maven.DefaultMaven; |
| import org.apache.maven.model.Plugin; |
| import org.apache.maven.model.building.ModelSource; |
| import org.apache.maven.model.building.UrlModelSource; |
| import org.apache.maven.plugin.BuildPluginManager; |
| import org.apache.maven.plugin.MavenPluginManager; |
| import org.apache.maven.plugin.descriptor.MojoDescriptor; |
| import org.apache.maven.plugin.descriptor.PluginDescriptor; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.maven.project.ProjectBuilder; |
| import org.apache.maven.project.ProjectBuildingException; |
| |
| import org.eclipse.m2e.core.MavenPlugin; |
| import org.eclipse.m2e.core.embedder.ArtifactKey; |
| import org.eclipse.m2e.core.embedder.ICallable; |
| import org.eclipse.m2e.core.embedder.IMavenExecutionContext; |
| import org.eclipse.m2e.core.internal.IMavenConstants; |
| import org.eclipse.m2e.core.internal.Messages; |
| import org.eclipse.m2e.core.internal.embedder.MavenExecutionContext; |
| import org.eclipse.m2e.core.internal.embedder.MavenImpl; |
| import org.eclipse.m2e.editor.xml.MvnIndexPlugin; |
| import org.eclipse.m2e.editor.xml.mojo.IMojoParameterMetadata; |
| import org.eclipse.m2e.editor.xml.mojo.IMojoParameterMetadataProvider; |
| import org.eclipse.m2e.editor.xml.mojo.MojoParameter; |
| import org.eclipse.m2e.editor.xml.mojo.PlexusConfigHelper; |
| |
| |
| /** |
| * @author atanasenko |
| */ |
| @SuppressWarnings("restriction") |
| public class MojoParameterMetadataProvider implements IMojoParameterMetadataProvider { |
| |
| private static final Logger log = LoggerFactory.getLogger(MojoParameterMetadataProvider.class); |
| |
| private static final Cache<String, MojoParameter> cache = CacheBuilder.newBuilder().maximumSize(100).softValues() |
| .build(); |
| |
| protected final MavenImpl maven; |
| |
| public MojoParameterMetadataProvider() { |
| maven = (MavenImpl) MavenPlugin.getMaven(); |
| } |
| |
| @Deprecated |
| public MojoParameter getClassConfiguration(ArtifactKey pluginKey, String className, IProgressMonitor monitor) |
| throws CoreException { |
| return getClassConfiguration(pluginKey, className); |
| } |
| |
| @Deprecated |
| public MojoParameter getMojoConfiguration(ArtifactKey pluginKey, Collection<String> mojos, IProgressMonitor monitor) |
| throws CoreException { |
| return getMojoConfiguration(pluginKey, mojos); |
| } |
| |
| @Deprecated |
| public MojoParameter getMojoConfiguration(ArtifactKey pluginKey, IProgressMonitor monitor) throws CoreException { |
| return getMojoConfiguration(pluginKey); |
| } |
| |
| @Deprecated |
| public MojoParameter getMojoConfiguration(ArtifactKey pluginKey, String mojo, IProgressMonitor monitor) |
| throws CoreException { |
| return getMojoConfiguration(pluginKey, mojo); |
| } |
| |
| public MojoParameter getClassConfiguration(final ArtifactKey pluginKey, final String className) throws CoreException { |
| |
| try { |
| String key = pluginKey.toPortableString() + "/" + className; |
| |
| return cache.get(key, new Callable<MojoParameter>() { |
| public MojoParameter call() throws Exception { |
| |
| return execute(pluginKey, new ICallable<MojoParameter>() { |
| public MojoParameter call(IMavenExecutionContext context, IProgressMonitor monitor) throws CoreException { |
| PluginDescriptor pd = getPluginDescriptor(pluginKey, context, monitor); |
| |
| List<MojoParameter> parameters = null; |
| if(pd != null) { |
| Class<?> clazz; |
| try { |
| clazz = pd.getClassRealm().loadClass(className); |
| } catch(ClassNotFoundException ex) { |
| return null; |
| } |
| parameters = new PlexusConfigHelper().loadParameters(pd.getClassRealm(), clazz, monitor); |
| } |
| return new MojoParameter("", className, parameters); //$NON-NLS-1$ |
| } |
| }); |
| } |
| }); |
| |
| } catch(ExecutionException e) { |
| Throwable t = e.getCause(); |
| if(t instanceof CoreException) { |
| throw (CoreException) t; |
| } |
| if(t instanceof RuntimeException) { |
| throw (RuntimeException) t; |
| } |
| throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, e.getMessage(), e)); |
| } |
| } |
| |
| public MojoParameter getMojoConfiguration(ArtifactKey pluginKey, final Collection<String> mojos) |
| throws CoreException { |
| List<MojoParameter> params = new ArrayList<>(); |
| Set<String> collected = new HashSet<>(); |
| for(String mojo : mojos) { |
| MojoParameter md = getMojoConfiguration(pluginKey, mojo); |
| for(MojoParameter p : md.getNestedParameters()) { |
| if(!collected.add(p.getName())) |
| continue; |
| params.add(p); |
| } |
| } |
| return new MojoParameter("", "", params); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| public MojoParameter getMojoConfiguration(ArtifactKey pluginKey) throws CoreException { |
| return getMojoConfiguration(pluginKey, "*"); //$NON-NLS-1$ |
| } |
| |
| public MojoParameter getMojoConfiguration(final ArtifactKey pluginKey, final String mojo) throws CoreException { |
| |
| MojoParameter predefParameters = getPredefined(pluginKey); |
| if(predefParameters != null) { |
| return predefParameters; |
| } |
| |
| String key = pluginKey.toPortableString() + "/mojo/" + (mojo == null ? "*" : mojo); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| try { |
| return cache.get(key, new Callable<MojoParameter>() { |
| public MojoParameter call() throws Exception { |
| |
| return execute(pluginKey, new ICallable<MojoParameter>() { |
| public MojoParameter call(IMavenExecutionContext context, IProgressMonitor monitor) throws CoreException { |
| PluginDescriptor pd = getPluginDescriptor(pluginKey, context, monitor); |
| |
| List<MojoParameter> parameters = null; |
| if(pd != null) { |
| parameters = loadMojoParameters(pd, mojo, monitor); |
| } |
| return new MojoParameter("", mojo, parameters); //$NON-NLS-1$ |
| } |
| }); |
| } |
| }); |
| |
| } catch(ExecutionException e) { |
| Throwable t = e.getCause(); |
| if(t instanceof CoreException) { |
| throw (CoreException) t; |
| } |
| if(t instanceof RuntimeException) { |
| throw (RuntimeException) t; |
| } |
| throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, e.getMessage(), e)); |
| } |
| } |
| |
| List<MojoParameter> loadMojoParameters(PluginDescriptor desc, String goal, IProgressMonitor monitor) |
| throws CoreException { |
| |
| PlexusConfigHelper helper = new PlexusConfigHelper(); |
| |
| if(goal.equals("*")) { //$NON-NLS-1$ |
| List<MojoParameter> parameters = new ArrayList<>(); |
| Set<String> collected = new HashSet<>(); |
| for(MojoDescriptor mojo : desc.getMojos()) { |
| for(MojoParameter p : loadMojoParameters(desc, mojo, helper, monitor)) { |
| if(collected.add(p.getName())) { |
| parameters.add(p); |
| } |
| } |
| } |
| return parameters; |
| } |
| return loadMojoParameters(desc, desc.getMojo(goal), helper, monitor); |
| } |
| |
| private MojoParameter getPredefined(ArtifactKey pluginKey) { |
| return PREDEF.get(pluginKey.getGroupId() + ":" + pluginKey.getArtifactId() + ":" + pluginKey.getVersion()); |
| } |
| |
| <T> T execute(final ArtifactKey pluginKey, final ICallable<T> callable) throws CoreException { |
| |
| final Object[] result = new Object[1]; |
| final CoreException[] innerException = new CoreException[1]; |
| |
| try { |
| PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(true, true, new IRunnableWithProgress() { |
| public void run(IProgressMonitor monitor) { |
| monitor.beginTask(org.eclipse.m2e.editor.xml.internal.Messages.PomTemplateContext_resolvingPlugin, 100); |
| try { |
| |
| MavenExecutionContext context = maven.createExecutionContext(); |
| context.getExecutionRequest().setCacheTransferError(false); |
| T res = context.execute(new ICallable<T>() { |
| public T call(IMavenExecutionContext context, IProgressMonitor monitor) throws CoreException { |
| MavenProject mp = getProject(context); |
| if(mp != null) { |
| return context.execute(mp, callable, monitor); |
| } |
| return null; |
| } |
| }, monitor); |
| |
| if(monitor.isCanceled()) |
| return; |
| result[0] = res; |
| |
| } catch(CoreException ex) { |
| if(monitor.isCanceled()) |
| return; |
| innerException[0] = ex; |
| } |
| |
| } |
| }); |
| } catch(InvocationTargetException | InterruptedException ex) { |
| throw new CoreException(new Status(IStatus.ERROR, MvnIndexPlugin.PLUGIN_ID, ex.getMessage(), ex)); |
| } |
| if(innerException[0] != null) { |
| throw innerException[0]; |
| } |
| |
| @SuppressWarnings("unchecked") |
| T res = (T) result[0]; |
| return res; |
| } |
| |
| MavenProject getProject(IMavenExecutionContext context) { |
| |
| ModelSource modelSource = new UrlModelSource(DefaultMaven.class.getResource("project/standalone.xml")); //$NON-NLS-1$ |
| try { |
| return lookup(ProjectBuilder.class).build(modelSource, context.newProjectBuildingRequest()).getProject(); |
| } catch(ProjectBuildingException | CoreException ex) { |
| log.warn(ex.getMessage()); |
| return null; |
| } |
| } |
| |
| PluginDescriptor getPluginDescriptor(ArtifactKey pluginKey, IMavenExecutionContext context, |
| IProgressMonitor monitor) { |
| PluginDescriptor desc; |
| |
| Plugin plugin = new Plugin(); |
| plugin.setGroupId(pluginKey.getGroupId()); |
| plugin.setArtifactId(pluginKey.getArtifactId()); |
| plugin.setVersion(pluginKey.getVersion()); |
| |
| List<RemoteRepository> remoteRepos = context.getSession().getCurrentProject().getRemotePluginRepositories(); |
| try { |
| desc = lookup(MavenPluginManager.class).getPluginDescriptor(plugin, remoteRepos, context.getRepositorySession()); |
| lookup(BuildPluginManager.class).getPluginRealm(context.getSession(), desc); |
| return desc; |
| } catch(Exception ex) { |
| log.warn(ex.getMessage()); |
| return null; |
| } |
| |
| } |
| |
| <T> T lookup(Class<T> clazz) throws CoreException { |
| try { |
| return maven.getPlexusContainer().lookup(clazz); |
| } catch(ComponentLookupException ex) { |
| throw new CoreException( |
| new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1, Messages.MavenImpl_error_lookup, ex)); |
| } |
| } |
| |
| List<MojoParameter> loadMojoParameters(PluginDescriptor desc, MojoDescriptor mojo, PlexusConfigHelper helper, |
| IProgressMonitor monitor) throws CoreException { |
| |
| IMojoParameterMetadata metadata = null; |
| String mojoConfigurator = mojo.getComponentConfigurator(); |
| if(mojoConfigurator != null) { |
| metadata = readMojoParameterMetadata(mojoConfigurator); |
| } |
| if(metadata == null) { |
| metadata = new DefaultMojoParameterMetadata(); |
| } |
| |
| return metadata.loadMojoParameters(desc, mojo, helper, monitor); |
| } |
| |
| public static final String EXTENSION_MOJO_PARAMETER_METADATA = MvnIndexPlugin.PLUGIN_ID + ".mojoParameterMetadata"; //$NON-NLS-1$ |
| |
| private static IMojoParameterMetadata readMojoParameterMetadata(String mojoConfigurator) { |
| |
| IExtensionRegistry registry = Platform.getExtensionRegistry(); |
| IExtensionPoint mappingsExtensionPoint = registry.getExtensionPoint(EXTENSION_MOJO_PARAMETER_METADATA); |
| if(mappingsExtensionPoint != null) { |
| IExtension[] mappingsExtensions = mappingsExtensionPoint.getExtensions(); |
| for(IExtension extension : mappingsExtensions) { |
| IConfigurationElement[] elements = extension.getConfigurationElements(); |
| for(IConfigurationElement element : elements) { |
| if(element.getName().equals("mojoParameterMetadata") //$NON-NLS-1$ |
| && mojoConfigurator.equals(element.getAttribute("configurator"))) { //$NON-NLS-1$ |
| try { |
| return (IMojoParameterMetadata) element.createExecutableExtension("class"); //$NON-NLS-1$ |
| } catch(CoreException ex) { |
| log.error(ex.getMessage(), ex); |
| } |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| private static final Map<String, MojoParameter> PREDEF; |
| |
| static { |
| // @formatter:off |
| PREDEF = ImmutableMap.<String, MojoParameter>of( |
| "org.eclipse.m2e:lifecycle-mapping:1.0.0", |
| new MojoParameter("", "", Collections.singletonList( |
| new MojoParameter("lifecycleMappingMetadata", "LifecycleMappingMetadata", Collections.singletonList( |
| new MojoParameter("pluginExecutions", "List<PluginExecution>", Collections.singletonList( |
| new MojoParameter("pluginExecution", "PluginExecution", Arrays.asList( |
| new MojoParameter("pluginExecutionFilter", "PluginExecutionFilter", Arrays.asList( |
| new MojoParameter("groupId", "String"), |
| new MojoParameter("artifactId", "String"), |
| new MojoParameter("versionRange", "String"), |
| new MojoParameter("goals", "List<String>", Collections.singletonList( |
| new MojoParameter("goal", "String").multiple() |
| )) |
| )), |
| new MojoParameter("action", "Action", Arrays.asList( |
| new MojoParameter("ignore", "void"), |
| new MojoParameter("execute", "Execute", Arrays.asList( |
| new MojoParameter("runOnIncremental", "boolean"), |
| new MojoParameter("runOnConfiguration", "boolean") |
| )) |
| )) |
| )).multiple() |
| )) |
| )) |
| )) |
| ); |
| // @formatter:on |
| } |
| |
| } |