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