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.Set;
27  import java.util.stream.Collectors;
28  import java.util.stream.Stream;
29  
30  import org.apache.maven.api.services.MessageBuilder;
31  import org.apache.maven.api.services.MessageBuilderFactory;
32  import org.apache.maven.api.xml.XmlNode;
33  import org.apache.maven.internal.xml.XmlNodeImpl;
34  import org.apache.maven.lifecycle.MojoExecutionConfigurator;
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.project.MavenProject;
41  import org.codehaus.plexus.util.xml.Xpp3Dom;
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  import static java.util.Arrays.stream;
46  
47  /**
48   * @since 3.3.1, MNG-5753
49   */
50  @Named
51  @Singleton
52  public class DefaultMojoExecutionConfigurator implements MojoExecutionConfigurator {
53      private final Logger logger = LoggerFactory.getLogger(getClass());
54  
55      @Inject
56      MessageBuilderFactory messageBuilderFactory;
57  
58      @Override
59      public void configure(MavenProject project, MojoExecution mojoExecution, boolean allowPluginLevelConfig) {
60          String g = mojoExecution.getPlugin().getGroupId();
61  
62          String a = mojoExecution.getPlugin().getArtifactId();
63  
64          Plugin plugin = findPlugin(g, a, project.getBuildPlugins());
65  
66          if (plugin == null && project.getPluginManagement() != null) {
67              plugin = findPlugin(g, a, project.getPluginManagement().getPlugins());
68          }
69  
70          if (plugin != null) {
71              PluginExecution pluginExecution =
72                      findPluginExecution(mojoExecution.getExecutionId(), plugin.getExecutions());
73  
74              XmlNode pomConfiguration = null;
75  
76              if (pluginExecution != null) {
77                  pomConfiguration = pluginExecution.getDelegate().getConfiguration();
78              } else if (allowPluginLevelConfig) {
79                  pomConfiguration = plugin.getDelegate().getConfiguration();
80              }
81  
82              XmlNode mojoConfiguration = mojoExecution.getConfiguration() != null
83                      ? mojoExecution.getConfiguration().getDom()
84                      : null;
85  
86              XmlNode mergedConfiguration = XmlNodeImpl.merge(mojoConfiguration, pomConfiguration);
87  
88              mojoExecution.setConfiguration(mergedConfiguration);
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 (executionId != null && !executionId.isEmpty()) {
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.getConfiguration() == null
118                 || mojoExecution.getConfiguration().getChildCount() == 0) {
119             return;
120         }
121 
122         MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
123 
124         // in first step get parameter names of current goal
125         Set<String> parametersNamesGoal = mojoDescriptor.getParameters().stream()
126                 .flatMap(this::getParameterNames)
127                 .collect(Collectors.toSet());
128 
129         Set<String> unknownParameters = getUnknownParameters(mojoExecution, parametersNamesGoal);
130 
131         if (unknownParameters.isEmpty()) {
132             return;
133         }
134 
135         // second step get parameter names of all plugin goals
136         Set<String> parametersNamesAll = mojoDescriptor.getPluginDescriptor().getMojos().stream()
137                 .flatMap(m -> m.getParameters().stream())
138                 .flatMap(this::getParameterNames)
139                 .collect(Collectors.toSet());
140 
141         unknownParameters = getUnknownParameters(mojoExecution, parametersNamesAll);
142 
143         unknownParameters.forEach(name -> {
144             MessageBuilder messageBuilder = messageBuilderFactory
145                     .builder()
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 Stream<String> getParameterNames(Parameter parameter) {
168         if (parameter.getAlias() != null) {
169             return Stream.of(parameter.getName(), parameter.getAlias());
170         } else {
171             return Stream.of(parameter.getName());
172         }
173     }
174 
175     private Set<String> getUnknownParameters(MojoExecution mojoExecution, Set<String> parameters) {
176         return stream(mojoExecution.getConfiguration().getChildren())
177                 .map(Xpp3Dom::getName)
178                 .filter(name -> !parameters.contains(name))
179                 .collect(Collectors.toSet());
180     }
181 }