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