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 javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.Optional;
28  import java.util.Set;
29  import java.util.stream.Collectors;
30  import java.util.stream.Stream;
31  
32  import org.apache.maven.lifecycle.MojoExecutionConfigurator;
33  import org.apache.maven.message.MessageBuilder;
34  import org.apache.maven.message.MessageBuilderFactory;
35  import org.apache.maven.model.Plugin;
36  import org.apache.maven.model.PluginExecution;
37  import org.apache.maven.plugin.MojoExecution;
38  import org.apache.maven.plugin.descriptor.MojoDescriptor;
39  import org.apache.maven.plugin.descriptor.Parameter;
40  import org.apache.maven.plugin.descriptor.PluginDescriptor;
41  import org.apache.maven.project.MavenProject;
42  import org.codehaus.plexus.util.StringUtils;
43  import org.codehaus.plexus.util.xml.Xpp3Dom;
44  import org.slf4j.Logger;
45  import org.slf4j.LoggerFactory;
46  
47  import static java.util.Arrays.stream;
48  
49  /**
50   * @since 3.3.1, MNG-5753
51   */
52  @Singleton
53  @Named
54  public class DefaultMojoExecutionConfigurator implements MojoExecutionConfigurator {
55      private final Logger logger = LoggerFactory.getLogger(getClass());
56  
57      @Inject
58      private MessageBuilderFactory messageBuilderFactory;
59  
60      @Override
61      public void configure(MavenProject project, MojoExecution mojoExecution, boolean allowPluginLevelConfig) {
62          String g = mojoExecution.getPlugin().getGroupId();
63  
64          String a = mojoExecution.getPlugin().getArtifactId();
65  
66          Plugin plugin = findPlugin(g, a, project.getBuildPlugins());
67  
68          if (plugin == null && project.getPluginManagement() != null) {
69              plugin = findPlugin(g, a, project.getPluginManagement().getPlugins());
70          }
71  
72          if (plugin != null) {
73              PluginExecution pluginExecution =
74                      findPluginExecution(mojoExecution.getExecutionId(), plugin.getExecutions());
75  
76              Xpp3Dom pomConfiguration = null;
77  
78              if (pluginExecution != null) {
79                  pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration();
80              } else if (allowPluginLevelConfig) {
81                  pomConfiguration = (Xpp3Dom) plugin.getConfiguration();
82              }
83  
84              Xpp3Dom mojoConfiguration = (pomConfiguration != null) ? new Xpp3Dom(pomConfiguration) : null;
85  
86              mojoConfiguration = Xpp3Dom.mergeXpp3Dom(mojoExecution.getConfiguration(), mojoConfiguration);
87  
88              mojoExecution.setConfiguration(mojoConfiguration);
89  
90              checkUnknownMojoConfigurationParameters(mojoExecution);
91          }
92      }
93  
94      private Plugin findPlugin(String groupId, String artifactId, Collection<Plugin> plugins) {
95          for (Plugin plugin : plugins) {
96              if (artifactId.equals(plugin.getArtifactId()) && groupId.equals(plugin.getGroupId())) {
97                  return plugin;
98              }
99          }
100 
101         return null;
102     }
103 
104     private PluginExecution findPluginExecution(String executionId, Collection<PluginExecution> executions) {
105         if (StringUtils.isNotEmpty(executionId)) {
106             for (PluginExecution execution : executions) {
107                 if (executionId.equals(execution.getId())) {
108                     return execution;
109                 }
110             }
111         }
112 
113         return null;
114     }
115 
116     private void checkUnknownMojoConfigurationParameters(MojoExecution mojoExecution) {
117         if (mojoExecution.getMojoDescriptor() == null
118                 || mojoExecution.getConfiguration() == null
119                 || mojoExecution.getConfiguration().getChildCount() == 0) {
120             return;
121         }
122 
123         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
124 
125         // in first step get parameter names of current goal
126         Set<String> parametersNamesGoal =
127                 Optional.ofNullable(mojoDescriptor.getParameters()).orElseGet(Collections::emptyList).stream()
128                         .flatMap(this::getParameterNames)
129                         .collect(Collectors.toSet());
130 
131         Set<String> unknownParameters = getUnknownParameters(mojoExecution, parametersNamesGoal);
132 
133         if (unknownParameters.isEmpty()) {
134             return;
135         }
136 
137         // second step get parameter names of all plugin goals
138         Set<String> parametersNamesAll = Optional.ofNullable(mojoDescriptor.getPluginDescriptor())
139                 .map(PluginDescriptor::getMojos)
140                 .orElseGet(Collections::emptyList)
141                 .stream()
142                 .filter(m -> m.getParameters() != null)
143                 .flatMap(m -> m.getParameters().stream())
144                 .flatMap(this::getParameterNames)
145                 .collect(Collectors.toSet());
146 
147         unknownParameters = getUnknownParameters(mojoExecution, parametersNamesAll);
148 
149         unknownParameters.stream()
150                 .filter(parameterName -> isNotReportPluginsForMavenSite(parameterName, mojoExecution))
151                 .forEach(name -> {
152                     MessageBuilder messageBuilder = messageBuilderFactory
153                             .builder()
154                             .warning("Parameter '")
155                             .warning(name)
156                             .warning("' is unknown for plugin '")
157                             .warning(mojoExecution.getArtifactId())
158                             .warning(":")
159                             .warning(mojoExecution.getVersion())
160                             .warning(":")
161                             .warning(mojoExecution.getGoal());
162 
163                     if (mojoExecution.getExecutionId() != null) {
164                         messageBuilder.warning(" (");
165                         messageBuilder.warning(mojoExecution.getExecutionId());
166                         messageBuilder.warning(")");
167                     }
168 
169                     messageBuilder.warning("'");
170 
171                     logger.warn(messageBuilder.toString());
172                 });
173     }
174 
175     private boolean isNotReportPluginsForMavenSite(String parameterName, MojoExecution mojoExecution) {
176         return !("reportPlugins".equals(parameterName) && "maven-site-plugin".equals(mojoExecution.getArtifactId()));
177     }
178 
179     private Stream<String> getParameterNames(Parameter parameter) {
180         if (parameter.getAlias() != null) {
181             return Stream.of(parameter.getName(), parameter.getAlias());
182         } else {
183             return Stream.of(parameter.getName());
184         }
185     }
186 
187     private Set<String> getUnknownParameters(MojoExecution mojoExecution, Set<String> parameters) {
188         return stream(mojoExecution.getConfiguration().getChildren())
189                 .map(Xpp3Dom::getName)
190                 .filter(name -> !parameters.contains(name))
191                 .collect(Collectors.toSet());
192     }
193 }