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.internal.impl;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Provider;
24  import javax.inject.Singleton;
25  
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Collections;
29  import java.util.HashSet;
30  import java.util.Iterator;
31  import java.util.LinkedHashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.Objects;
35  import java.util.Optional;
36  import java.util.Set;
37  import java.util.stream.Collectors;
38  import java.util.stream.Stream;
39  
40  import org.apache.maven.api.Lifecycle;
41  import org.apache.maven.api.model.Plugin;
42  import org.apache.maven.api.services.LifecycleRegistry;
43  import org.apache.maven.api.services.LookupException;
44  import org.apache.maven.api.spi.ExtensibleEnumProvider;
45  import org.apache.maven.api.spi.LifecycleProvider;
46  import org.apache.maven.lifecycle.mapping.LifecyclePhase;
47  import org.codehaus.plexus.PlexusContainer;
48  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
49  
50  import static java.util.Arrays.asList;
51  import static java.util.Collections.singleton;
52  import static org.apache.maven.internal.impl.Lifecycles.phase;
53  import static org.apache.maven.internal.impl.Lifecycles.plugin;
54  
55  /**
56   * TODO: this is session scoped as SPI can contribute.
57   */
58  @Named
59  @Singleton
60  public class DefaultLifecycleRegistry implements LifecycleRegistry {
61  
62      private final List<LifecycleProvider> providers;
63  
64      public DefaultLifecycleRegistry() {
65          this(Collections.emptyList());
66      }
67  
68      @Inject
69      public DefaultLifecycleRegistry(List<LifecycleProvider> providers) {
70          List<LifecycleProvider> p = new ArrayList<>(providers);
71          p.add(() -> List.of(new CleanLifecycle(), new DefaultLifecycle(), new SiteLifecycle(), new WrapperLifecycle()));
72          this.providers = p;
73          // validate lifecycle
74          for (Lifecycle lifecycle : this) {
75              Set<String> set = new HashSet<>();
76              lifecycle.phases().forEach(phase -> {
77                  if (!set.add(phase.name())) {
78                      throw new IllegalArgumentException(
79                              "Found duplicated phase '" + phase.name() + "' in '" + lifecycle.id() + "' lifecycle");
80                  }
81              });
82          }
83      }
84  
85      @Override
86      public Iterator<Lifecycle> iterator() {
87          return stream().toList().iterator();
88      }
89  
90      @Override
91      public Stream<Lifecycle> stream() {
92          return providers.stream().map(ExtensibleEnumProvider::provides).flatMap(Collection::stream);
93      }
94  
95      @Override
96      public Optional<Lifecycle> lookup(String id) {
97          return stream().filter(lf -> Objects.equals(id, lf.id())).findAny();
98      }
99  
100     @Named
101     @Singleton
102     public static class LifecycleWrapperProvider implements LifecycleProvider {
103         private final PlexusContainer container;
104 
105         @Inject
106         public LifecycleWrapperProvider(PlexusContainer container) {
107             this.container = container;
108         }
109 
110         @Override
111         public Collection<Lifecycle> provides() {
112             try {
113                 Map<String, org.apache.maven.lifecycle.Lifecycle> all =
114                         container.lookupMap(org.apache.maven.lifecycle.Lifecycle.class);
115                 return all.keySet().stream()
116                         .filter(id -> !Lifecycle.CLEAN.equals(id)
117                                 && !Lifecycle.DEFAULT.equals(id)
118                                 && !Lifecycle.SITE.equals(id)
119                                 && !Lifecycle.WRAPPER.equals(id))
120                         .map(id -> wrap(all.get(id)))
121                         .collect(Collectors.toList());
122             } catch (ComponentLookupException e) {
123                 throw new LookupException(e);
124             }
125         }
126 
127         private Lifecycle wrap(org.apache.maven.lifecycle.Lifecycle lifecycle) {
128             return new Lifecycle() {
129                 @Override
130                 public String id() {
131                     return lifecycle.getId();
132                 }
133 
134                 @Override
135                 public Collection<Phase> phases() {
136                     return lifecycle.getPhases().stream()
137                             .map(name -> (Phase) new Phase() {
138                                 @Override
139                                 public String name() {
140                                     return name;
141                                 }
142 
143                                 @Override
144                                 public List<Plugin> plugins() {
145                                     Map<String, LifecyclePhase> lfPhases = lifecycle.getDefaultLifecyclePhases();
146                                     LifecyclePhase phase = lfPhases != null ? lfPhases.get(name) : null;
147                                     if (phase != null) {
148                                         Map<String, Plugin> plugins = new LinkedHashMap<>();
149                                         DefaultPackagingRegistry.parseLifecyclePhaseDefinitions(plugins, name, phase);
150                                         return plugins.values().stream().toList();
151                                     }
152                                     return List.of();
153                                 }
154                             })
155                             .toList();
156                 }
157             };
158         }
159     }
160 
161     static class WrappedLifecycle extends org.apache.maven.lifecycle.Lifecycle {
162         WrappedLifecycle(Lifecycle lifecycle) {
163             super(lifecycle);
164         }
165     }
166 
167     abstract static class BaseLifecycleProvider implements Provider<org.apache.maven.lifecycle.Lifecycle> {
168         @Inject
169         private PlexusContainer lookup;
170 
171         private final String name;
172 
173         BaseLifecycleProvider(String name) {
174             this.name = name;
175         }
176 
177         @Override
178         public org.apache.maven.lifecycle.Lifecycle get() {
179             try {
180                 LifecycleRegistry registry = lookup.lookup(LifecycleRegistry.class);
181                 return new WrappedLifecycle(registry.require(name));
182             } catch (ComponentLookupException e) {
183                 throw new LookupException(e);
184             }
185         }
186     }
187 
188     @Singleton
189     @Named(Lifecycle.CLEAN)
190     static class CleanLifecycleProvider extends BaseLifecycleProvider {
191         CleanLifecycleProvider() {
192             super(Lifecycle.CLEAN);
193         }
194     }
195 
196     @Singleton
197     @Named(Lifecycle.DEFAULT)
198     static class DefaultLifecycleProvider extends BaseLifecycleProvider {
199         DefaultLifecycleProvider() {
200             super(Lifecycle.DEFAULT);
201         }
202     }
203 
204     @Singleton
205     @Named(Lifecycle.SITE)
206     static class SiteLifecycleProvider extends BaseLifecycleProvider {
207         SiteLifecycleProvider() {
208             super(Lifecycle.SITE);
209         }
210     }
211 
212     @Singleton
213     @Named(Lifecycle.WRAPPER)
214     static class WrapperLifecycleProvider extends BaseLifecycleProvider {
215         WrapperLifecycleProvider() {
216             super(Lifecycle.WRAPPER);
217         }
218     }
219 
220     static class CleanLifecycle implements Lifecycle {
221 
222         private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.2.0";
223 
224         @Override
225         public String id() {
226             return Lifecycle.CLEAN;
227         }
228 
229         @Override
230         public Collection<Phase> phases() {
231             return asList(
232                     phase("pre-clean"),
233                     phase(
234                             "clean",
235                             plugin(
236                                     "org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION
237                                             + ":clean",
238                                     "clean")),
239                     phase("post-clean"));
240         }
241     }
242 
243     static class DefaultLifecycle implements Lifecycle {
244         @Override
245         public String id() {
246             return Lifecycle.DEFAULT;
247         }
248 
249         @Override
250         public Collection<Phase> phases() {
251             return asList(
252                     phase("validate"),
253                     phase("initialize"),
254                     phase("generate-sources"),
255                     phase("process-sources"),
256                     phase("generate-resources"),
257                     phase("process-resources"),
258                     phase("compile"),
259                     phase("process-classes"),
260                     phase("generate-test-sources"),
261                     phase("process-test-sources"),
262                     phase("generate-test-resources"),
263                     phase("process-test-resources"),
264                     phase("test-compile"),
265                     phase("process-test-classes"),
266                     phase("test"),
267                     phase("prepare-package"),
268                     phase("package"),
269                     phase("pre-integration-test"),
270                     phase("integration-test"),
271                     phase("post-integration-test"),
272                     phase("verify"),
273                     phase("install"),
274                     phase("deploy"));
275         }
276     }
277 
278     static class SiteLifecycle implements Lifecycle {
279 
280         private static final String MAVEN_SITE_PLUGIN_VERSION = "3.12.1";
281 
282         @Override
283         public String id() {
284             return Lifecycle.SITE;
285         }
286 
287         @Override
288         public Collection<Phase> phases() {
289             return asList(
290                     phase("pre-site"),
291                     phase(
292                             "site",
293                             plugin(
294                                     "org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION + ":site",
295                                     "site")),
296                     phase("post-site"),
297                     phase(
298                             "site-deploy",
299                             plugin(
300                                     "org.apache.maven.plugins:maven-site-plugin:" + MAVEN_SITE_PLUGIN_VERSION
301                                             + ":deploy",
302                                     "site-deploy")));
303         }
304     }
305 
306     static class WrapperLifecycle implements Lifecycle {
307 
308         private static final String MAVEN_WRAPPER_PLUGIN_VERSION = "3.2.0";
309 
310         @Override
311         public String id() {
312             return WRAPPER;
313         }
314 
315         @Override
316         public Collection<Phase> phases() {
317             return singleton(phase(
318                     "wrapper",
319                     plugin(
320                             "org.apache.maven.plugins:maven-wrapper-plugin:" + MAVEN_WRAPPER_PLUGIN_VERSION
321                                     + ":wrapper",
322                             "wrapper")));
323         }
324     }
325 }