blob: b380123955fdc7687f6d922576793782fe17cbfb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.maven.lifecycle.internal;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.internal.xml.XmlNodeImpl;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.InvalidPluginDescriptorException;
import org.apache.maven.plugin.MojoNotFoundException;
import org.apache.maven.plugin.PluginDescriptorParsingException;
import org.apache.maven.plugin.PluginNotFoundException;
import org.apache.maven.plugin.PluginResolutionException;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.prefix.DefaultPluginPrefixRequest;
import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException;
import org.apache.maven.plugin.prefix.PluginPrefixRequest;
import org.apache.maven.plugin.prefix.PluginPrefixResolver;
import org.apache.maven.plugin.prefix.PluginPrefixResult;
import org.apache.maven.plugin.version.DefaultPluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionRequest;
import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.plugin.version.PluginVersionResolver;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* <p>
* Resolves dependencies for the artifacts in context of the lifecycle build
* </p>
* <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
*
* @since 3.0
*/
@Named
@Singleton
public class MojoDescriptorCreator {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final PluginVersionResolver pluginVersionResolver;
private final BuildPluginManager pluginManager;
private final PluginPrefixResolver pluginPrefixResolver;
private final LifecyclePluginResolver lifecyclePluginResolver;
@Inject
public MojoDescriptorCreator(
PluginVersionResolver pluginVersionResolver,
BuildPluginManager pluginManager,
PluginPrefixResolver pluginPrefixResolver,
LifecyclePluginResolver lifecyclePluginResolver) {
this.pluginVersionResolver = pluginVersionResolver;
this.pluginManager = pluginManager;
this.pluginPrefixResolver = pluginPrefixResolver;
this.lifecyclePluginResolver = lifecyclePluginResolver;
}
private Plugin findPlugin(String groupId, String artifactId, Collection<Plugin> plugins) {
for (Plugin plugin : plugins) {
if (artifactId.equals(plugin.getArtifactId()) && groupId.equals(plugin.getGroupId())) {
return plugin;
}
}
return null;
}
public static XmlNode convert(org.apache.maven.api.plugin.descriptor.MojoDescriptor mojoDescriptor) {
List<XmlNode> children = mojoDescriptor.getParameters().stream()
.filter(p -> p.getDefaultValue() != null || p.getExpression() != null)
.map(p -> new XmlNodeImpl(
p.getName(),
p.getExpression(),
p.getDefaultValue() != null
? Collections.singletonMap("default-value", p.getDefaultValue())
: null,
null,
null))
.collect(Collectors.toList());
return new XmlNodeImpl("configuration", null, null, children, null);
}
public static org.codehaus.plexus.util.xml.Xpp3Dom convert(MojoDescriptor mojoDescriptor) {
PlexusConfiguration c = mojoDescriptor.getMojoConfiguration();
List<XmlNode> children = new ArrayList<>();
PlexusConfiguration[] ces = c.getChildren();
if (ces != null) {
for (PlexusConfiguration ce : ces) {
String value = ce.getValue(null);
String defaultValue = ce.getAttribute("default-value", null);
if (value != null || defaultValue != null) {
XmlNodeImpl e = new XmlNodeImpl(
ce.getName(),
value,
defaultValue != null ? Collections.singletonMap("default-value", defaultValue) : null,
null,
null);
children.add(e);
}
}
}
XmlNodeImpl dom = new XmlNodeImpl("configuration", null, null, children, null);
return new org.codehaus.plexus.util.xml.Xpp3Dom(dom);
}
// org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process@executionId
public MojoDescriptor getMojoDescriptor(String task, MavenSession session, MavenProject project)
throws PluginNotFoundException, PluginResolutionException, PluginDescriptorParsingException,
MojoNotFoundException, NoPluginFoundForPrefixException, InvalidPluginDescriptorException,
PluginVersionResolutionException {
String goal = null;
Plugin plugin = null;
String[] tok = task.split(":");
int numTokens = tok.length;
if (numTokens >= 4) {
// We have everything that we need
//
// org.apache.maven.plugins:maven-remote-resources-plugin:1.0:process
//
// groupId
// artifactId
// version
// goal
//
plugin = new Plugin();
plugin.setGroupId(tok[0]);
plugin.setArtifactId(tok[1]);
plugin.setVersion(tok[2]);
goal = tok[3];
// This won't be valid, but it constructs something easy to read in the error message
for (int idx = 4; idx < tok.length; idx++) {
goal += ":" + tok[idx];
}
} else if (numTokens == 3) {
// groupId:artifactId:goal or pluginPrefix:version:goal (since Maven 3.9.0)
String firstToken = tok[0];
// groupId or pluginPrefix? heuristics: groupId contains dot (.) but not pluginPrefix
if (firstToken.contains(".")) {
// We have everything that we need except the version
//
// org.apache.maven.plugins:maven-remote-resources-plugin:???:process
//
// groupId
// artifactId
// ???
// goal
//
plugin = new Plugin();
plugin.setGroupId(firstToken);
plugin.setArtifactId(tok[1]);
} else {
// pluginPrefix:version:goal, like remote-resources:3.5.0:process
plugin = findPluginForPrefix(firstToken, session);
plugin.setVersion(tok[1]);
}
goal = tok[2];
} else {
// We have a prefix and goal
//
// idea:idea
//
String prefix = tok[0];
if (numTokens == 2) {
goal = tok[1];
} else {
// goal was missing - pass through to MojoNotFoundException
goal = "";
}
// This is the case where someone has executed a single goal from the command line
// of the form:
//
// mvn remote-resources:process
//
// From the metadata stored on the server which has been created as part of a standard
// Maven plugin deployment we will find the right PluginDescriptor from the remote
// repository.
plugin = findPluginForPrefix(prefix, session);
}
int executionIdx = goal.indexOf('@');
if (executionIdx > 0) {
goal = goal.substring(0, executionIdx);
}
injectPluginDeclarationFromProject(plugin, project);
// If there is no version to be found then we need to look in the repository metadata for
// this plugin and see what's specified as the latest release.
//
if (plugin.getVersion() == null) {
resolvePluginVersion(plugin, session, project);
}
return pluginManager.getMojoDescriptor(
plugin, goal, project.getRemotePluginRepositories(), session.getRepositorySession());
}
// TODO take repo mans into account as one may be aggregating prefixes of many
// TODO collect at the root of the repository, read the one at the root, and fetch remote if something is missing
// or the user forces the issue
public Plugin findPluginForPrefix(String prefix, MavenSession session) throws NoPluginFoundForPrefixException {
// [prefix]:[goal]
if (session.getCurrentProject() != null) {
try {
lifecyclePluginResolver.resolveMissingPluginVersions(session.getCurrentProject(), session);
} catch (PluginVersionResolutionException e) {
// not critical here
logger.debug(e.getMessage(), e);
}
}
PluginPrefixRequest prefixRequest = new DefaultPluginPrefixRequest(prefix, session);
PluginPrefixResult prefixResult = pluginPrefixResolver.resolve(prefixRequest);
Plugin plugin = new Plugin();
plugin.setGroupId(prefixResult.getGroupId());
plugin.setArtifactId(prefixResult.getArtifactId());
return plugin;
}
private void resolvePluginVersion(Plugin plugin, MavenSession session, MavenProject project)
throws PluginVersionResolutionException {
PluginVersionRequest versionRequest = new DefaultPluginVersionRequest(
plugin, session.getRepositorySession(), project.getRemotePluginRepositories());
plugin.setVersion(pluginVersionResolver.resolve(versionRequest).getVersion());
}
private void injectPluginDeclarationFromProject(Plugin plugin, MavenProject project) {
Plugin pluginInPom = findPlugin(plugin, project.getBuildPlugins());
if (pluginInPom == null && project.getPluginManagement() != null) {
pluginInPom = findPlugin(plugin, project.getPluginManagement().getPlugins());
}
if (pluginInPom != null) {
if (plugin.getVersion() == null) {
plugin.setVersion(pluginInPom.getVersion());
}
plugin.setDependencies(new ArrayList<>(pluginInPom.getDependencies()));
}
}
private Plugin findPlugin(Plugin plugin, Collection<Plugin> plugins) {
return findPlugin(plugin.getGroupId(), plugin.getArtifactId(), plugins);
}
}