| /* |
| * 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.enforcer.rules; |
| |
| import javax.inject.Inject; |
| import javax.inject.Named; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.Set; |
| |
| import org.apache.maven.BuildFailureException; |
| import org.apache.maven.RepositoryUtils; |
| import org.apache.maven.artifact.Artifact; |
| import org.apache.maven.artifact.factory.ArtifactFactory; |
| import org.apache.maven.artifact.repository.ArtifactRepository; |
| import org.apache.maven.artifact.resolver.ArtifactNotFoundException; |
| import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; |
| import org.apache.maven.artifact.versioning.VersionRange; |
| import org.apache.maven.enforcer.rule.api.EnforcerRuleError; |
| import org.apache.maven.enforcer.rule.api.EnforcerRuleException; |
| import org.apache.maven.enforcer.rules.utils.EnforcerRuleUtils; |
| import org.apache.maven.enforcer.rules.utils.ExpressionEvaluator; |
| import org.apache.maven.enforcer.rules.utils.PluginWrapper; |
| import org.apache.maven.execution.MavenSession; |
| import org.apache.maven.lifecycle.DefaultLifecycles; |
| import org.apache.maven.lifecycle.Lifecycle; |
| import org.apache.maven.lifecycle.LifecycleExecutionException; |
| import org.apache.maven.lifecycle.mapping.LifecycleMapping; |
| import org.apache.maven.model.BuildBase; |
| import org.apache.maven.model.Model; |
| import org.apache.maven.model.ModelBase; |
| import org.apache.maven.model.Plugin; |
| import org.apache.maven.model.PluginConfiguration; |
| import org.apache.maven.model.PluginContainer; |
| import org.apache.maven.model.Profile; |
| import org.apache.maven.model.ReportPlugin; |
| import org.apache.maven.model.Reporting; |
| import org.apache.maven.plugin.InvalidPluginException; |
| import org.apache.maven.plugin.PluginManager; |
| import org.apache.maven.plugin.PluginManagerException; |
| import org.apache.maven.plugin.PluginNotFoundException; |
| import org.apache.maven.plugin.descriptor.PluginDescriptor; |
| import org.apache.maven.plugin.version.PluginVersionNotFoundException; |
| import org.apache.maven.plugin.version.PluginVersionResolutionException; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.maven.rtinfo.RuntimeInformation; |
| import org.apache.maven.settings.Settings; |
| import org.codehaus.plexus.PlexusContainer; |
| import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; |
| import org.codehaus.plexus.component.repository.exception.ComponentLookupException; |
| import org.codehaus.plexus.util.StringUtils; |
| import org.eclipse.aether.RepositorySystem; |
| import org.eclipse.aether.resolution.ArtifactRequest; |
| import org.eclipse.aether.resolution.ArtifactResolutionException; |
| |
| import static java.util.Optional.ofNullable; |
| |
| /** |
| * This rule will enforce that all plugins specified in the poms have a version declared. |
| * |
| * @author <a href="mailto:brianf@apache.org">Brian Fox</a> |
| */ |
| @Named("requirePluginVersions") |
| public final class RequirePluginVersions extends AbstractStandardEnforcerRule { |
| |
| /** |
| * Don't allow the LATEST identifier. |
| */ |
| private boolean banLatest = true; |
| |
| /** |
| * Don't allow the RELEASE identifier. |
| */ |
| private boolean banRelease = true; |
| |
| /** |
| * Don't allow snapshot plugins. |
| */ |
| private boolean banSnapshots = true; |
| |
| /** |
| * Don't allow timestamp snapshot plugins. |
| */ |
| private boolean banTimestamps = true; |
| |
| /** |
| * @since 3.0.0 |
| */ |
| private boolean banMavenDefaults = true; |
| |
| /** |
| * The comma separated list of phases that should be used to find lifecycle plugin bindings. The default value is |
| * "clean,deploy,site". |
| */ |
| private String phases = "clean,deploy,site"; |
| |
| /** |
| * Additional plugins to enforce have versions. These are plugins that may not be in the poms but are used anyway, |
| * like help, eclipse etc. <br> |
| * The plugins should be specified in the form: <code>group:artifactId</code>. |
| */ |
| private List<String> additionalPlugins; |
| |
| /** |
| * Plugins to skip for version enforcement. The plugins should be specified in the form: |
| * <code>group:artifactId</code>. NOTE: This is deprecated, use unCheckedPluginList instead. |
| */ |
| private List<String> unCheckedPlugins; |
| |
| /** |
| * Same as unCheckedPlugins but as a comma list to better support properties. Sample form: |
| * <code>group:artifactId,group2:artifactId2</code> |
| * |
| * @since 1.0-beta-1 |
| */ |
| private String unCheckedPluginList; |
| |
| /** The phase to lifecycle map. */ |
| private Map<String, Lifecycle> phaseToLifecycleMap; |
| |
| /** The lifecycles. */ |
| private Collection<Lifecycle> lifecycles; |
| |
| /** The plugin manager. */ |
| private final PluginManager pluginManager; |
| |
| /** The factory. */ |
| private final ArtifactFactory factory; |
| |
| private final RepositorySystem repositorySystem; |
| |
| /** The session. */ |
| private final MavenSession session; |
| |
| /** The utils. */ |
| private final EnforcerRuleUtils utils; |
| |
| private final RuntimeInformation runtimeInformation; |
| |
| private final DefaultLifecycles defaultLifeCycles; |
| |
| private final MavenProject project; |
| |
| private final ExpressionEvaluator evaluator; |
| |
| private final PlexusContainer container; |
| |
| @Inject |
| public RequirePluginVersions( |
| PluginManager pluginManager, |
| ArtifactFactory factory, |
| RepositorySystem repositorySystem, |
| MavenSession session, |
| EnforcerRuleUtils utils, |
| RuntimeInformation runtimeInformation, |
| DefaultLifecycles defaultLifeCycles, |
| MavenProject project, |
| ExpressionEvaluator evaluator, |
| PlexusContainer container) { |
| this.pluginManager = Objects.requireNonNull(pluginManager); |
| this.factory = Objects.requireNonNull(factory); |
| this.repositorySystem = Objects.requireNonNull(repositorySystem); |
| this.session = Objects.requireNonNull(session); |
| this.utils = Objects.requireNonNull(utils); |
| this.runtimeInformation = Objects.requireNonNull(runtimeInformation); |
| this.defaultLifeCycles = Objects.requireNonNull(defaultLifeCycles); |
| this.project = Objects.requireNonNull(project); |
| this.evaluator = Objects.requireNonNull(evaluator); |
| this.container = Objects.requireNonNull(container); |
| } |
| |
| @Override |
| public void execute() throws EnforcerRuleException { |
| |
| try { |
| // get the various expressions out of the helper. |
| |
| lifecycles = defaultLifeCycles.getLifeCycles(); |
| |
| // get all the plugins that are bound to the specified lifecycles |
| Set<Plugin> allPlugins = getBoundPlugins(project, phases); |
| |
| // insert any additional plugins specified by the user. |
| allPlugins = addAdditionalPlugins(allPlugins, additionalPlugins); |
| allPlugins.addAll(getProfilePlugins(project)); |
| |
| // pull out any we should skip |
| allPlugins = |
| removeUncheckedPlugins(combineUncheckedPlugins(unCheckedPlugins, unCheckedPluginList), allPlugins); |
| |
| // there's nothing to do here |
| if (allPlugins.isEmpty()) { |
| getLog().info("No plugin bindings found."); |
| return; |
| } else { |
| getLog().debug("All Plugins in use: " + allPlugins); |
| } |
| |
| // get all the plugins that are mentioned in the pom (and parents) |
| List<PluginWrapper> pluginWrappers = getAllPluginEntries(project); |
| |
| for (PluginWrapper pluginWrapper : pluginWrappers) { |
| getLog().debug("pluginWrappers: " + pluginWrapper.getGroupId() + ":" + pluginWrapper.getArtifactId() |
| + ":" + pluginWrapper.getVersion() + " source: " + pluginWrapper.getSource()); |
| } |
| // now look for the versions that aren't valid and add to a list. |
| List<Plugin> failures = new ArrayList<>(); |
| |
| for (Plugin plugin : allPlugins) { |
| if (!hasValidVersionSpecified(plugin, pluginWrappers)) { |
| failures.add(plugin); |
| } |
| } |
| |
| // if anything was found, log it then append the optional message. |
| if (!failures.isEmpty()) { |
| handleMessagesToTheUser(project, failures); |
| } |
| } catch (PluginNotFoundException | LifecycleExecutionException e) { |
| throw new EnforcerRuleException(e.getLocalizedMessage(), e); |
| } |
| } |
| |
| private void handleMessagesToTheUser(MavenProject project, List<Plugin> failures) throws EnforcerRuleException { |
| StringBuilder newMsg = new StringBuilder(); |
| newMsg.append("Some plugins are missing valid versions or depend on Maven "); |
| newMsg.append(runtimeInformation.getMavenVersion()); |
| newMsg.append(" defaults"); |
| handleBanMessages(newMsg); |
| newMsg.append(System.lineSeparator()); |
| for (Plugin plugin : failures) { |
| newMsg.append(" "); |
| newMsg.append(plugin.getGroupId()); |
| newMsg.append(":"); |
| newMsg.append(plugin.getArtifactId()); |
| |
| try { |
| newMsg.append(". \tThe version currently in use is "); |
| |
| Plugin currentPlugin = findCurrentPlugin(plugin, project); |
| |
| if (currentPlugin == null) { |
| newMsg.append("unknown"); |
| } else { |
| newMsg.append(currentPlugin.getVersion()); |
| |
| if (PluginWrapper.isVersionFromDefaultLifecycleBindings(currentPlugin) |
| .orElse(false)) { |
| newMsg.append(" via default lifecycle bindings"); |
| } else { |
| String msg = PluginWrapper.isVersionFromSuperpom(currentPlugin) |
| .filter(b -> b) |
| .map(t -> " via super POM") |
| // for Maven 3.6.0 or before (MNG-6593 / MNG-6600) |
| .orElse(" via super POM or default lifecycle bindings"); |
| newMsg.append(msg); |
| } |
| } |
| } catch (Exception e) { |
| // lots can go wrong here. Don't allow any issues trying to |
| // determine the issue stop me |
| getLog().debug("Exception while determining plugin Version " + e.getMessage()); |
| newMsg.append(". Unable to determine the plugin version."); |
| } |
| newMsg.append(System.lineSeparator()); |
| } |
| String message = getMessage(); |
| if (message != null && !message.isEmpty()) { |
| newMsg.append(message); |
| } |
| |
| throw new EnforcerRuleException(newMsg.toString()); |
| } |
| |
| private void handleBanMessages(StringBuilder newMsg) { |
| if (banLatest || banRelease || banSnapshots || banTimestamps) { |
| List<String> banList = new ArrayList<>(); |
| if (banLatest) { |
| banList.add("LATEST"); |
| } |
| if (banRelease) { |
| banList.add("RELEASE"); |
| } |
| if (banSnapshots) { |
| banList.add("SNAPSHOT"); |
| if (banTimestamps) { |
| banList.add("TIMESTAMP SNAPSHOT"); |
| } |
| } |
| if (!banList.isEmpty()) { |
| newMsg.append(" ("); |
| newMsg.append(String.join(", ", banList)); |
| newMsg.append(" as plugin version are not allowed)"); |
| } |
| } |
| } |
| |
| /** |
| * Remove the plugins that the user doesn't want to check. |
| * |
| * @param uncheckedPlugins |
| * @param plugins |
| * @return The plugins which have been removed. |
| */ |
| Set<Plugin> removeUncheckedPlugins(Collection<String> uncheckedPlugins, Set<Plugin> plugins) |
| throws EnforcerRuleError { |
| if (uncheckedPlugins != null && !uncheckedPlugins.isEmpty()) { |
| for (String pluginKey : uncheckedPlugins) { |
| Plugin plugin = parsePluginString(pluginKey, "UncheckedPlugins"); |
| plugins.remove(plugin); |
| } |
| } |
| return plugins; |
| } |
| |
| /** |
| * Combines the old Collection with the new comma separated list. |
| * |
| * @param uncheckedPlugins a new collections |
| * @param uncheckedPluginsList a list to merge |
| * @return List of unchecked plugins. |
| */ |
| public Collection<String> combineUncheckedPlugins( |
| Collection<String> uncheckedPlugins, String uncheckedPluginsList) { |
| // if the comma list is empty, then there's nothing to do here. |
| if (uncheckedPluginsList != null && !uncheckedPluginsList.isEmpty()) { |
| // make sure there is a collection to add to. |
| if (uncheckedPlugins == null) { |
| uncheckedPlugins = new HashSet<>(); |
| } else if (!uncheckedPlugins.isEmpty()) { |
| getLog().warn("The parameter 'unCheckedPlugins' is deprecated. Use 'unCheckedPluginList' instead"); |
| } |
| |
| uncheckedPlugins.addAll(Arrays.asList(uncheckedPluginsList.split(","))); |
| } |
| return uncheckedPlugins; |
| } |
| |
| /** |
| * Add the additional plugins if they don't exist yet. |
| * |
| * @param existing the existing |
| * @param additional the additional |
| * @return the sets the |
| * @throws EnforcerRuleError the enforcer error |
| */ |
| public Set<Plugin> addAdditionalPlugins(Set<Plugin> existing, List<String> additional) throws EnforcerRuleError { |
| if (additional != null) { |
| for (String pluginString : additional) { |
| Plugin plugin = parsePluginString(pluginString, "AdditionalPlugins"); |
| |
| if (existing == null) { |
| existing = new HashSet<>(); |
| existing.add(plugin); |
| } else if (!existing.contains(plugin)) { |
| existing.add(plugin); |
| } |
| } |
| } |
| return existing; |
| } |
| |
| /** |
| * Helper method to parse and inject a Plugin. |
| * |
| * @param pluginString a plugin description to parse |
| * @param field a source of pluginString |
| * @return the prepared plugin |
| */ |
| private Plugin parsePluginString(String pluginString, String field) throws EnforcerRuleError { |
| if (pluginString != null) { |
| String[] pluginStrings = pluginString.split(":"); |
| if (pluginStrings.length == 2) { |
| Plugin plugin = new Plugin(); |
| plugin.setGroupId(StringUtils.strip(pluginStrings[0])); |
| plugin.setArtifactId(StringUtils.strip(pluginStrings[1])); |
| |
| return plugin; |
| } else { |
| throw new EnforcerRuleError("Invalid " + field + " string: " + pluginString); |
| } |
| } else { |
| throw new EnforcerRuleError("Invalid " + field + " string: " + pluginString); |
| } |
| } |
| |
| /** |
| * Finds the plugins that are listed in active profiles. |
| * |
| * @param project the project |
| * @return the profile plugins |
| */ |
| public Set<Plugin> getProfilePlugins(MavenProject project) { |
| Set<Plugin> result = new HashSet<>(); |
| List<Profile> profiles = project.getActiveProfiles(); |
| if (profiles != null && !profiles.isEmpty()) { |
| for (Profile p : profiles) { |
| BuildBase b = p.getBuild(); |
| if (b != null) { |
| List<Plugin> plugins = b.getPlugins(); |
| if (plugins != null) { |
| result.addAll(plugins); |
| } |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Given a plugin, this will retrieve the matching plugin artifact from the model. |
| * |
| * @param plugin plugin to lookup |
| * @param project project to search |
| * @return matching plugin, <code>null</code> if not found. |
| */ |
| private Plugin findCurrentPlugin(Plugin plugin, MavenProject project) throws EnforcerRuleException { |
| Plugin found = null; |
| try { |
| Model model = project.getModel(); |
| Map<String, Plugin> plugins = model.getBuild().getPluginsAsMap(); |
| found = plugins.get(plugin.getKey()); |
| } catch (NullPointerException e) { |
| // nothing to do here |
| } |
| |
| if (found == null) { |
| Artifact artifact = factory.createPluginArtifact( |
| plugin.getGroupId(), plugin.getArtifactId(), VersionRange.createFromVersion("LATEST")); |
| |
| try { |
| repositorySystem.resolveArtifact( |
| session.getRepositorySession(), |
| new ArtifactRequest( |
| RepositoryUtils.toArtifact(artifact), |
| session.getCurrentProject().getRemotePluginRepositories(), |
| "resolvePlugin")); |
| } catch (ArtifactResolutionException e) { |
| throw new EnforcerRuleException("Unable to resolve the plugin " + artifact.getArtifactId(), e); |
| } |
| plugin.setVersion(artifact.getVersion()); |
| |
| found = plugin; |
| } |
| |
| return found; |
| } |
| |
| /** |
| * Gets the plugins that are bound to the defined phases. This does not find plugins bound in the pom to a phase |
| * later than the plugin is executing. |
| * |
| * @param project the project |
| * @param thePhases the phases |
| * @return the bound plugins |
| * @throws PluginNotFoundException the plugin not found exception |
| * @throws LifecycleExecutionException the lifecycle execution exception |
| */ |
| private Set<Plugin> getBoundPlugins(MavenProject project, String thePhases) |
| throws PluginNotFoundException, LifecycleExecutionException { |
| |
| Set<Plugin> allPlugins = new HashSet<>(); |
| |
| // lookup the bindings for all the passed in phases |
| String[] lifecyclePhases = thePhases.split(","); |
| for (int i = 0; i < lifecyclePhases.length; i++) { |
| String lifecyclePhase = lifecyclePhases[i]; |
| if (lifecyclePhase != null && !lifecyclePhase.isEmpty()) { |
| try { |
| Lifecycle lifecycle = getLifecycleForPhase(lifecyclePhase); |
| getLog().debug("getBoundPlugins(): " + project.getId() + " " + lifecyclePhase + " " |
| + lifecycle.getId()); |
| allPlugins.addAll(getAllPlugins(project, lifecycle)); |
| } catch (BuildFailureException e) { |
| // i'm going to swallow this because the |
| // user may have declared a phase that |
| // doesn't exist for every module. |
| } |
| } |
| } |
| return allPlugins; |
| } |
| |
| /** |
| * Checks for valid version specified. Checks to see if the version is specified for the plugin. Can optionally ban |
| * "RELEASE" or "LATEST" even if specified. |
| * |
| * @param source the source |
| * @param pluginWrappers the plugins |
| * @return true, if successful |
| */ |
| public boolean hasValidVersionSpecified(Plugin source, List<PluginWrapper> pluginWrappers) { |
| boolean found = false; |
| boolean status = false; |
| for (PluginWrapper plugin : pluginWrappers) { |
| // find the matching plugin entry |
| if (isMatchingPlugin(source, plugin)) { |
| found = true; |
| // found the entry. now see if the version is specified |
| String version = plugin.getVersion(); |
| try { |
| version = (String) evaluator.evaluate(version); |
| } catch (ExpressionEvaluationException e) { |
| return false; |
| } |
| |
| if (isValidVersion(version)) { |
| getLog().debug("checking for notEmpty and notIsWhitespace(): " + version); |
| if (banRelease && version.equals("RELEASE")) { |
| return false; |
| } |
| |
| if (banLatest && version.equals("LATEST")) { |
| return false; |
| } |
| |
| if (banSnapshots && isSnapshot(version)) { |
| return false; |
| } |
| // the version was specified and not |
| // banned. It's ok. Keep looking through the list to make |
| // sure it's not using a banned version somewhere else. |
| |
| status = true; |
| |
| if (!banRelease && !banLatest && !banSnapshots) { |
| // no need to keep looking |
| break; |
| } |
| } |
| } |
| } |
| if (!found) { |
| getLog().debug("plugin " + source.getGroupId() + ":" + source.getArtifactId() + " not found"); |
| } |
| return status; |
| } |
| |
| private boolean isValidVersion(String version) { |
| return (version != null && !version.isEmpty()) && !StringUtils.isWhitespace(version); |
| } |
| |
| private boolean isMatchingPlugin(Plugin source, PluginWrapper plugin) { |
| return source.getArtifactId().equals(plugin.getArtifactId()) |
| && source.getGroupId().equals(plugin.getGroupId()); |
| } |
| |
| /** |
| * Checks if is snapshot. |
| * |
| * @param baseVersion the base version |
| * @return true, if is snapshot |
| */ |
| private boolean isSnapshot(String baseVersion) { |
| if (banTimestamps) { |
| return Artifact.VERSION_FILE_PATTERN.matcher(baseVersion).matches() |
| || baseVersion.endsWith(Artifact.SNAPSHOT_VERSION); |
| } else { |
| return baseVersion.endsWith(Artifact.SNAPSHOT_VERSION); |
| } |
| } |
| |
| /* |
| * Uses borrowed lifecycle code to get a list of all plugins bound to the lifecycle. |
| */ |
| |
| /** |
| * Gets the all plugins. |
| * |
| * @param project the project |
| * @param lifecycle the lifecycle |
| * @return the all plugins |
| * @throws PluginNotFoundException the plugin not found exception |
| * @throws LifecycleExecutionException the lifecycle execution exception |
| */ |
| private Set<Plugin> getAllPlugins(MavenProject project, Lifecycle lifecycle) |
| throws PluginNotFoundException, LifecycleExecutionException { |
| |
| getLog().debug("RequirePluginVersions.getAllPlugins:"); |
| |
| Set<Plugin> plugins = new HashSet<>(); |
| // first, bind those associated with the packaging |
| Map<String, String> mappings = findMappingsForLifecycle(project, lifecycle); |
| |
| for (Map.Entry<String, String> entry : mappings.entrySet()) { |
| getLog().debug(" lifecycleMapping = " + entry.getKey()); |
| String pluginsForLifecycle = (String) entry.getValue(); |
| getLog().debug(" plugins = " + pluginsForLifecycle); |
| if (pluginsForLifecycle != null && !pluginsForLifecycle.isEmpty()) { |
| String pluginList[] = pluginsForLifecycle.split(","); |
| for (String plugin : pluginList) { |
| plugin = StringUtils.strip(plugin); |
| getLog().debug(" plugin = " + plugin); |
| String tokens[] = plugin.split(":"); |
| getLog().debug(" GAV = " + Arrays.asList(tokens)); |
| |
| Plugin p = new Plugin(); |
| p.setGroupId(tokens[0]); |
| p.setArtifactId(tokens[1]); |
| plugins.add(p); |
| } |
| } |
| } |
| |
| plugins.addAll(project.getBuildPlugins()); |
| |
| return plugins; |
| } |
| |
| /* |
| * NOTE: All the code following this point was scooped from the DefaultLifecycleExecutor. There must be a better way |
| * but for now it should work. |
| */ |
| |
| /** |
| * Gets the phase to lifecycle map. |
| * |
| * @return the phase to lifecycle map |
| * @throws LifecycleExecutionException the lifecycle execution exception |
| */ |
| public Map<String, Lifecycle> getPhaseToLifecycleMap() throws LifecycleExecutionException { |
| if (phaseToLifecycleMap == null) { |
| phaseToLifecycleMap = new HashMap<>(); |
| |
| for (Lifecycle lifecycle : lifecycles) { |
| List<String> phases = lifecycle.getPhases(); |
| for (String phase : phases) { |
| getLog().debug("getPhaseToLifecycleMap(): phase: " + phase); |
| if (phaseToLifecycleMap.containsKey(phase)) { |
| Lifecycle prevLifecycle = (Lifecycle) phaseToLifecycleMap.get(phase); |
| throw new LifecycleExecutionException("Phase '" + phase |
| + "' is defined in more than one lifecycle: '" + lifecycle.getId() + "' and '" |
| + prevLifecycle.getId() + "'"); |
| } else { |
| phaseToLifecycleMap.put(phase, lifecycle); |
| } |
| } |
| } |
| } |
| return phaseToLifecycleMap; |
| } |
| |
| /** |
| * Gets the lifecycle for phase. |
| * |
| * @param phase the phase |
| * @return the lifecycle for phase |
| * @throws BuildFailureException the build failure exception |
| * @throws LifecycleExecutionException the lifecycle execution exception |
| */ |
| private Lifecycle getLifecycleForPhase(String phase) throws BuildFailureException, LifecycleExecutionException { |
| Lifecycle lifecycle = getPhaseToLifecycleMap().get(phase); |
| |
| if (lifecycle == null) { |
| throw new BuildFailureException("Unable to find lifecycle for phase '" + phase + "'"); |
| } |
| return lifecycle; |
| } |
| |
| /** |
| * Find mappings for lifecycle. |
| * |
| * @param project the project |
| * @param lifecycle the lifecycle |
| * @return the map |
| * @throws LifecycleExecutionException the lifecycle execution exception |
| * @throws PluginNotFoundException the plugin not found exception |
| */ |
| private Map<String, String> findMappingsForLifecycle(MavenProject project, Lifecycle lifecycle) |
| throws LifecycleExecutionException, PluginNotFoundException { |
| String packaging = project.getPackaging(); |
| Map<String, String> mappings = null; |
| |
| LifecycleMapping m = (LifecycleMapping) findExtension( |
| project, LifecycleMapping.ROLE, packaging, session.getSettings(), session.getLocalRepository()); |
| if (m != null) { |
| mappings = m.getPhases(lifecycle.getId()); |
| } |
| |
| Map<String, String> defaultMappings = lifecycle.getDefaultPhases(); |
| |
| if (mappings == null) { |
| try { |
| m = container.lookup(LifecycleMapping.class, packaging); |
| mappings = m.getPhases(lifecycle.getId()); |
| } catch (ComponentLookupException e) { |
| if (defaultMappings == null) { |
| throw new LifecycleExecutionException( |
| "Cannot find lifecycle mapping for packaging: \'" + packaging + "\'.", e); |
| } |
| } |
| } |
| |
| if (mappings == null) { |
| if (defaultMappings == null) { |
| throw new LifecycleExecutionException( |
| "Cannot find lifecycle mapping for packaging: \'" + packaging + "\', and there is no default"); |
| } else { |
| mappings = defaultMappings; |
| } |
| } |
| |
| return mappings; |
| } |
| |
| /** |
| * Find extension. |
| * |
| * @param project the project |
| * @param role the role |
| * @param roleHint the role hint |
| * @param settings the settings |
| * @param localRepository the local repository |
| * @return the object |
| * @throws LifecycleExecutionException the lifecycle execution exception |
| * @throws PluginNotFoundException the plugin not found exception |
| */ |
| private Object findExtension( |
| MavenProject project, String role, String roleHint, Settings settings, ArtifactRepository localRepository) |
| throws LifecycleExecutionException, PluginNotFoundException { |
| Object pluginComponent = null; |
| |
| List<Plugin> buildPlugins = project.getBuildPlugins(); |
| for (Plugin plugin : buildPlugins) { |
| if (plugin.isExtensions()) { |
| verifyPlugin(plugin, project, settings, localRepository); |
| |
| // TODO: if moved to the plugin manager we |
| // already have the descriptor from above |
| // and so do can lookup the container |
| // directly |
| try { |
| pluginComponent = pluginManager.getPluginComponent(plugin, role, roleHint); |
| |
| if (pluginComponent != null) { |
| break; |
| } |
| } catch (ComponentLookupException e) { |
| getLog().debug("Unable to find the lifecycle component in the extension " + e.getMessage()); |
| } catch (PluginManagerException e) { |
| throw new LifecycleExecutionException( |
| "Error getting extensions from the plugin '" + plugin.getKey() + "': " + e.getMessage(), e); |
| } |
| } |
| } |
| return pluginComponent; |
| } |
| |
| /** |
| * Verify plugin. |
| * |
| * @param plugin the plugin |
| * @param project the project |
| * @param settings the settings |
| * @param localRepository the local repository |
| * @return the plugin descriptor |
| * @throws LifecycleExecutionException the lifecycle execution exception |
| * @throws PluginNotFoundException the plugin not found exception |
| */ |
| private PluginDescriptor verifyPlugin( |
| Plugin plugin, MavenProject project, Settings settings, ArtifactRepository localRepository) |
| throws LifecycleExecutionException, PluginNotFoundException { |
| PluginDescriptor pluginDescriptor; |
| try { |
| pluginDescriptor = pluginManager.verifyPlugin(plugin, project, settings, localRepository); |
| } catch (PluginManagerException e) { |
| throw new LifecycleExecutionException( |
| "Internal error in the plugin manager getting plugin '" + plugin.getKey() + "': " + e.getMessage(), |
| e); |
| } catch (PluginVersionResolutionException |
| | InvalidVersionSpecificationException |
| | InvalidPluginException |
| | PluginVersionNotFoundException |
| | org.apache.maven.artifact.resolver.ArtifactResolutionException |
| | ArtifactNotFoundException e) { |
| throw new LifecycleExecutionException(e.getMessage(), e); |
| } |
| return pluginDescriptor; |
| } |
| |
| /** |
| * Gets all plugin entries in build.plugins, build.pluginManagement.plugins, profile.build.plugins, reporting and |
| * profile.reporting in this project and all parents |
| * |
| * @param project the project |
| * @return the all plugin entries wrapped in a PluginWrapper Object |
| */ |
| private List<PluginWrapper> getAllPluginEntries(MavenProject project) { |
| List<PluginWrapper> plugins = new ArrayList<>(); |
| // now find all the plugin entries, either in |
| // build.plugins or build.pluginManagement.plugins, profiles.plugins and reporting |
| |
| getPlugins(plugins, project.getModel()); |
| getReportingPlugins(plugins, project.getModel()); |
| getPluginManagementPlugins(plugins, project.getModel()); |
| addPluginsInProfiles(plugins, project.getModel()); |
| |
| return plugins; |
| } |
| |
| private void addPluginsInProfiles(List<PluginWrapper> plugins, Model model) { |
| List<Profile> profiles = ofNullable(model).map(Model::getProfiles).orElseGet(Collections::emptyList); |
| for (Profile profile : profiles) { |
| getProfilePlugins(plugins, profile); |
| getProfileReportingPlugins(plugins, profile); |
| getProfilePluginManagementPlugins(plugins, profile); |
| } |
| } |
| |
| private void getProfilePluginManagementPlugins(List<PluginWrapper> plugins, Profile profile) { |
| List<Plugin> modelPlugins = ofNullable(profile) |
| .map(Profile::getBuild) |
| .map(PluginConfiguration::getPluginManagement) |
| .map(PluginContainer::getPlugins) |
| .orElseGet(Collections::emptyList); |
| plugins.addAll(PluginWrapper.addAll(utils.resolvePlugins(modelPlugins), banMavenDefaults)); |
| } |
| |
| private void getProfileReportingPlugins(List<PluginWrapper> plugins, Profile profile) { |
| List<ReportPlugin> modelReportPlugins = ofNullable(profile) |
| .map(ModelBase::getReporting) |
| .map(Reporting::getPlugins) |
| .orElseGet(Collections::emptyList); |
| // add the reporting plugins |
| plugins.addAll(PluginWrapper.addAll(utils.resolveReportPlugins(modelReportPlugins), banMavenDefaults)); |
| } |
| |
| private void getProfilePlugins(List<PluginWrapper> plugins, Profile profile) { |
| List<Plugin> modelPlugins = ofNullable(profile) |
| .map(Profile::getBuild) |
| .map(PluginContainer::getPlugins) |
| .orElseGet(Collections::emptyList); |
| plugins.addAll(PluginWrapper.addAll(utils.resolvePlugins(modelPlugins), banMavenDefaults)); |
| } |
| |
| private void getPlugins(List<PluginWrapper> plugins, Model model) { |
| List<Plugin> modelPlugins = ofNullable(model) |
| .map(Model::getBuild) |
| .map(PluginContainer::getPlugins) |
| .orElseGet(Collections::emptyList); |
| plugins.addAll(PluginWrapper.addAll(utils.resolvePlugins(modelPlugins), banMavenDefaults)); |
| } |
| |
| private void getPluginManagementPlugins(List<PluginWrapper> plugins, Model model) { |
| List<Plugin> modelPlugins = ofNullable(model) |
| .map(Model::getBuild) |
| .map(PluginConfiguration::getPluginManagement) |
| .map(PluginContainer::getPlugins) |
| .orElseGet(Collections::emptyList); |
| plugins.addAll(PluginWrapper.addAll(utils.resolvePlugins(modelPlugins), banMavenDefaults)); |
| } |
| |
| private void getReportingPlugins(List<PluginWrapper> plugins, Model model) { |
| List<ReportPlugin> modelReportPlugins = ofNullable(model) |
| .map(ModelBase::getReporting) |
| .map(Reporting::getPlugins) |
| .orElseGet(Collections::emptyList); |
| // add the reporting plugins |
| plugins.addAll(PluginWrapper.addAll(utils.resolveReportPlugins(modelReportPlugins), banMavenDefaults)); |
| } |
| |
| /** |
| * Sets the ban latest. |
| * |
| * @param theBanLatest the banLatest to set |
| */ |
| public void setBanLatest(boolean theBanLatest) { |
| this.banLatest = theBanLatest; |
| } |
| |
| /** |
| * Sets the ban release. |
| * |
| * @param theBanRelease the banRelease to set |
| */ |
| public void setBanRelease(boolean theBanRelease) { |
| this.banRelease = theBanRelease; |
| } |
| |
| /** |
| * Checks if is ban snapshots. |
| * |
| * @return the banSnapshots |
| */ |
| public boolean isBanSnapshots() { |
| return this.banSnapshots; |
| } |
| |
| /** |
| * Sets the ban snapshots. |
| * |
| * @param theBanSnapshots the banSnapshots to set |
| */ |
| public void setBanSnapshots(boolean theBanSnapshots) { |
| this.banSnapshots = theBanSnapshots; |
| } |
| |
| /** |
| * Sets the ban timestamps. |
| * |
| * @param theBanTimestamps the banTimestamps to set |
| */ |
| public void setBanTimestamps(boolean theBanTimestamps) { |
| this.banTimestamps = theBanTimestamps; |
| } |
| |
| @Override |
| public String toString() { |
| return String.format( |
| "RequirePluginVersions[message=%s, banLatest=%b, banRelease=%b, banSnapshots=%b, banTimestamps=%b, phases=%s, additionalPlugins=%s, unCheckedPluginList=%s, unCheckedPlugins=%s]", |
| getMessage(), |
| banLatest, |
| banRelease, |
| banSnapshots, |
| banTimestamps, |
| phases, |
| additionalPlugins, |
| unCheckedPluginList, |
| unCheckedPlugins); |
| } |
| } |