1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.model.plugin;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.LinkedHashMap;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.stream.Collectors;
32  
33  import org.apache.maven.api.model.Build;
34  import org.apache.maven.api.model.Model;
35  import org.apache.maven.api.model.Plugin;
36  import org.apache.maven.api.model.PluginContainer;
37  import org.apache.maven.api.model.PluginExecution;
38  import org.apache.maven.api.model.PluginManagement;
39  import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer;
40  import org.apache.maven.model.building.ModelBuildingRequest;
41  import org.apache.maven.model.building.ModelProblem.Severity;
42  import org.apache.maven.model.building.ModelProblem.Version;
43  import org.apache.maven.model.building.ModelProblemCollector;
44  import org.apache.maven.model.building.ModelProblemCollectorRequest;
45  import org.apache.maven.model.merge.MavenModelMerger;
46  
47  
48  
49  
50  
51  @Named
52  @Singleton
53  public class DefaultLifecycleBindingsInjector implements LifecycleBindingsInjector {
54  
55      private final LifecycleBindingsMerger merger = new LifecycleBindingsMerger();
56  
57      private final LifeCyclePluginAnalyzer lifecycle;
58  
59      @Inject
60      public DefaultLifecycleBindingsInjector(LifeCyclePluginAnalyzer lifecycle) {
61          this.lifecycle = lifecycle;
62      }
63  
64      public void injectLifecycleBindings(
65              org.apache.maven.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems) {
66          String packaging = model.getPackaging();
67  
68          Collection<org.apache.maven.model.Plugin> defaultPlugins =
69                  lifecycle.getPluginsBoundByDefaultToAllLifecycles(packaging);
70  
71          if (defaultPlugins == null) {
72              problems.add(new ModelProblemCollectorRequest(Severity.ERROR, Version.BASE)
73                      .setMessage("Unknown packaging: " + packaging)
74                      .setLocation(model.getLocation("packaging")));
75          } else if (!defaultPlugins.isEmpty()) {
76              List<Plugin> plugins = defaultPlugins.stream()
77                      .map(org.apache.maven.model.Plugin::getDelegate)
78                      .collect(Collectors.toList());
79              Model lifecycleModel = Model.newBuilder()
80                      .build(Build.newBuilder().plugins(plugins).build())
81                      .build();
82              model.update(merger.merge(model.getDelegate(), lifecycleModel));
83          }
84      }
85  
86      
87  
88  
89      protected static class LifecycleBindingsMerger extends MavenModelMerger {
90  
91          private static final String PLUGIN_MANAGEMENT = "plugin-management";
92  
93          public Model merge(Model target, Model source) {
94              Build targetBuild = target.getBuild();
95              if (targetBuild == null) {
96                  targetBuild = Build.newInstance();
97              }
98  
99              Map<Object, Object> context =
100                     Collections.singletonMap(PLUGIN_MANAGEMENT, targetBuild.getPluginManagement());
101 
102             Build.Builder builder = Build.newBuilder(targetBuild);
103             mergePluginContainer_Plugins(builder, targetBuild, source.getBuild(), false, context);
104 
105             return target.withBuild(builder.build());
106         }
107 
108         @SuppressWarnings({"checkstyle:methodname"})
109         @Override
110         protected void mergePluginContainer_Plugins(
111                 PluginContainer.Builder builder,
112                 PluginContainer target,
113                 PluginContainer source,
114                 boolean sourceDominant,
115                 Map<Object, Object> context) {
116             List<Plugin> src = source.getPlugins();
117             if (!src.isEmpty()) {
118                 List<Plugin> tgt = target.getPlugins();
119 
120                 Map<Object, Plugin> merged = new LinkedHashMap<>((src.size() + tgt.size()) * 2);
121 
122                 for (Plugin element : tgt) {
123                     Object key = getPluginKey().apply(element);
124                     merged.put(key, element);
125                 }
126 
127                 Map<Object, Plugin> added = new LinkedHashMap<>();
128 
129                 for (Plugin element : src) {
130                     Object key = getPluginKey().apply(element);
131                     Plugin existing = merged.get(key);
132                     if (existing != null) {
133                         element = mergePlugin(existing, element, sourceDominant, context);
134                     } else {
135                         added.put(key, element);
136                     }
137                     merged.put(key, element);
138                 }
139 
140                 if (!added.isEmpty()) {
141                     PluginManagement pluginMgmt = (PluginManagement) context.get(PLUGIN_MANAGEMENT);
142                     if (pluginMgmt != null) {
143                         for (Plugin managedPlugin : pluginMgmt.getPlugins()) {
144                             Object key = getPluginKey().apply(managedPlugin);
145                             Plugin addedPlugin = added.get(key);
146                             if (addedPlugin != null) {
147                                 Plugin plugin =
148                                         mergePlugin(managedPlugin, addedPlugin, sourceDominant, Collections.emptyMap());
149                                 merged.put(key, plugin);
150                             }
151                         }
152                     }
153                 }
154 
155                 List<Plugin> result = new ArrayList<>(merged.values());
156 
157                 builder.plugins(result);
158             }
159         }
160 
161         @Override
162         protected void mergePluginExecution_Priority(
163                 PluginExecution.Builder builder,
164                 PluginExecution target,
165                 PluginExecution source,
166                 boolean sourceDominant,
167                 Map<Object, Object> context) {
168             if (target.getPriority() > source.getPriority()) {
169                 builder.priority(source.getPriority());
170                 builder.location("priority", source.getLocation("priority"));
171             }
172         }
173         
174 
175     }
176 }