View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.lifecycle.internal;
20  
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.Optional;
24  import java.util.Set;
25  import java.util.stream.Collectors;
26  import java.util.stream.Stream;
27  
28  import org.apache.maven.lifecycle.MojoExecutionConfigurator;
29  import org.apache.maven.model.Plugin;
30  import org.apache.maven.model.PluginExecution;
31  import org.apache.maven.plugin.MojoExecution;
32  import org.apache.maven.plugin.descriptor.MojoDescriptor;
33  import org.apache.maven.plugin.descriptor.Parameter;
34  import org.apache.maven.plugin.descriptor.PluginDescriptor;
35  import org.apache.maven.project.MavenProject;
36  import org.apache.maven.shared.utils.logging.MessageBuilder;
37  import org.apache.maven.shared.utils.logging.MessageUtils;
38  import org.codehaus.plexus.component.annotations.Component;
39  import org.codehaus.plexus.util.StringUtils;
40  import org.codehaus.plexus.util.xml.Xpp3Dom;
41  import org.slf4j.Logger;
42  import org.slf4j.LoggerFactory;
43  
44  import static java.util.Arrays.stream;
45  
46  /**
47   * @since 3.3.1, MNG-5753
48   */
49  @Component(role = MojoExecutionConfigurator.class)
50  public class DefaultMojoExecutionConfigurator implements MojoExecutionConfigurator {
51      private final Logger logger = LoggerFactory.getLogger(getClass());
52  
53      @Override
54      public void configure(MavenProject project, MojoExecution mojoExecution, boolean allowPluginLevelConfig) {
55          String g = mojoExecution.getPlugin().getGroupId();
56  
57          String a = mojoExecution.getPlugin().getArtifactId();
58  
59          Plugin plugin = findPlugin(g, a, project.getBuildPlugins());
60  
61          if (plugin == null && project.getPluginManagement() != null) {
62              plugin = findPlugin(g, a, project.getPluginManagement().getPlugins());
63          }
64  
65          if (plugin != null) {
66              PluginExecution pluginExecution =
67                      findPluginExecution(mojoExecution.getExecutionId(), plugin.getExecutions());
68  
69              Xpp3Dom pomConfiguration = null;
70  
71              if (pluginExecution != null) {
72                  pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration();
73              } else if (allowPluginLevelConfig) {
74                  pomConfiguration = (Xpp3Dom) plugin.getConfiguration();
75              }
76  
77              Xpp3Dom mojoConfiguration = (pomConfiguration != null) ? new Xpp3Dom(pomConfiguration) : null;
78  
79              mojoConfiguration = Xpp3Dom.mergeXpp3Dom(mojoExecution.getConfiguration(), mojoConfiguration);
80  
81              mojoExecution.setConfiguration(mojoConfiguration);
82  
83              checkUnknownMojoConfigurationParameters(mojoExecution);
84          }
85      }
86  
87      private Plugin findPlugin(String groupId, String artifactId, Collection<Plugin> plugins) {
88          for (Plugin plugin : plugins) {
89              if (artifactId.equals(plugin.getArtifactId()) && groupId.equals(plugin.getGroupId())) {
90                  return plugin;
91              }
92          }
93  
94          return null;
95      }
96  
97      private PluginExecution findPluginExecution(String executionId, Collection<PluginExecution> executions) {
98          if (StringUtils.isNotEmpty(executionId)) {
99              for (PluginExecution execution : executions) {
100                 if (executionId.equals(execution.getId())) {
101                     return execution;
102                 }
103             }
104         }
105 
106         return null;
107     }
108 
109     private void checkUnknownMojoConfigurationParameters(MojoExecution mojoExecution) {
110         if (mojoExecution.getMojoDescriptor() == null
111                 || mojoExecution.getConfiguration() == null
112                 || mojoExecution.getConfiguration().getChildCount() == 0) {
113             return;
114         }
115 
116         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
117 
118         // in first step get parameter names of current goal
119         Set<String> parametersNamesGoal =
120                 Optional.ofNullable(mojoDescriptor.getParameters()).orElseGet(Collections::emptyList).stream()
121                         .flatMap(this::getParameterNames)
122                         .collect(Collectors.toSet());
123 
124         Set<String> unknownParameters = getUnknownParameters(mojoExecution, parametersNamesGoal);
125 
126         if (unknownParameters.isEmpty()) {
127             return;
128         }
129 
130         // second step get parameter names of all plugin goals
131         Set<String> parametersNamesAll = Optional.ofNullable(mojoDescriptor.getPluginDescriptor())
132                 .map(PluginDescriptor::getMojos)
133                 .orElseGet(Collections::emptyList)
134                 .stream()
135                 .filter(m -> m.getParameters() != null)
136                 .flatMap(m -> m.getParameters().stream())
137                 .flatMap(this::getParameterNames)
138                 .collect(Collectors.toSet());
139 
140         unknownParameters = getUnknownParameters(mojoExecution, parametersNamesAll);
141 
142         unknownParameters.stream()
143                 .filter(parameterName -> isNotReportPluginsForMavenSite(parameterName, mojoExecution))
144                 .forEach(name -> {
145                     MessageBuilder messageBuilder = MessageUtils.buffer()
146                             .warning("Parameter '")
147                             .warning(name)
148                             .warning("' is unknown for plugin '")
149                             .warning(mojoExecution.getArtifactId())
150                             .warning(":")
151                             .warning(mojoExecution.getVersion())
152                             .warning(":")
153                             .warning(mojoExecution.getGoal());
154 
155                     if (mojoExecution.getExecutionId() != null) {
156                         messageBuilder.warning(" (");
157                         messageBuilder.warning(mojoExecution.getExecutionId());
158                         messageBuilder.warning(")");
159                     }
160 
161                     messageBuilder.warning("'");
162 
163                     logger.warn(messageBuilder.toString());
164                 });
165     }
166 
167     private boolean isNotReportPluginsForMavenSite(String parameterName, MojoExecution mojoExecution) {
168         return !("reportPlugins".equals(parameterName) && "maven-site-plugin".equals(mojoExecution.getArtifactId()));
169     }
170 
171     private Stream<String> getParameterNames(Parameter parameter) {
172         if (parameter.getAlias() != null) {
173             return Stream.of(parameter.getName(), parameter.getAlias());
174         } else {
175             return Stream.of(parameter.getName());
176         }
177     }
178 
179     private Set<String> getUnknownParameters(MojoExecution mojoExecution, Set<String> parameters) {
180         return stream(mojoExecution.getConfiguration().getChildren())
181                 .map(Xpp3Dom::getName)
182                 .filter(name -> !parameters.contains(name))
183                 .collect(Collectors.toSet());
184     }
185 }