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;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.HashMap;
24  import java.util.LinkedHashMap;
25  import java.util.LinkedHashSet;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.codehaus.plexus.component.annotations.Component;
31  import org.codehaus.plexus.component.annotations.Requirement;
32  import org.codehaus.plexus.logging.Logger;
33  import org.codehaus.plexus.util.StringUtils;
34  
35  /**
36   * @since 3.0
37   * @author Jason van Zyl
38   * @author Kristian Rosenvold
39   */
40  // TODO The configuration for the lifecycle needs to be externalized so that I can use the annotations properly for the
41  // wiring and reference and external source for the lifecycle configuration.
42  @Component(role = DefaultLifecycles.class)
43  public class DefaultLifecycles {
44      public static final String[] STANDARD_LIFECYCLES = {"clean", "default", "site"};
45  
46      // @Configuration(source="org/apache/maven/lifecycle/lifecycles.xml")
47  
48      @Requirement(role = Lifecycle.class)
49      private Map<String, Lifecycle> lifecycles;
50  
51      @Requirement
52      private Logger logger;
53  
54      public DefaultLifecycles() {}
55  
56      public DefaultLifecycles(Map<String, Lifecycle> lifecycles, Logger logger) {
57          this.lifecycles = new LinkedHashMap<>();
58          this.logger = logger;
59          this.lifecycles = lifecycles;
60      }
61  
62      public Lifecycle get(String key) {
63          return getPhaseToLifecycleMap().get(key);
64      }
65  
66      /**
67       * We use this to map all phases to the lifecycle that contains it. This is used so that a user can specify the
68       * phase they want to execute and we can easily determine what lifecycle we need to run.
69       *
70       * @return A map of lifecycles, indexed on id
71       */
72      public Map<String, Lifecycle> getPhaseToLifecycleMap() {
73          // If people are going to make their own lifecycles then we need to tell people how to namespace them correctly
74          // so that they don't interfere with internally defined lifecycles.
75  
76          HashMap<String, Lifecycle> phaseToLifecycleMap = new HashMap<>();
77  
78          for (Lifecycle lifecycle : getLifeCycles()) {
79              if (logger.isDebugEnabled()) {
80                  logger.debug("Lifecycle " + lifecycle);
81              }
82  
83              for (String phase : lifecycle.getPhases()) {
84                  // The first definition wins.
85                  if (!phaseToLifecycleMap.containsKey(phase)) {
86                      phaseToLifecycleMap.put(phase, lifecycle);
87                  } else {
88                      Lifecycle original = phaseToLifecycleMap.get(phase);
89                      logger.warn("Duplicated lifecycle phase " + phase + ". Defined in " + original.getId()
90                              + " but also in " + lifecycle.getId());
91                  }
92              }
93          }
94  
95          return phaseToLifecycleMap;
96      }
97  
98      /**
99       * Returns an ordered list of lifecycles
100      */
101     public List<Lifecycle> getLifeCycles() {
102         // ensure canonical order of standard lifecycles
103         Map<String, Lifecycle> lifecycles = new LinkedHashMap<>(this.lifecycles);
104 
105         LinkedHashSet<String> lifecycleNames = new LinkedHashSet<>(Arrays.asList(STANDARD_LIFECYCLES));
106         lifecycleNames.addAll(lifecycles.keySet());
107 
108         ArrayList<Lifecycle> result = new ArrayList<>();
109         for (String name : lifecycleNames) {
110             Lifecycle lifecycle = lifecycles.get(name);
111             if (lifecycle.getId() == null) {
112                 throw new NullPointerException("A lifecycle must have an id.");
113             }
114             result.add(lifecycle);
115         }
116 
117         return result;
118     }
119 
120     public String getLifecyclePhaseList() {
121         Set<String> phases = new LinkedHashSet<>();
122 
123         for (Lifecycle lifecycle : getLifeCycles()) {
124             phases.addAll(lifecycle.getPhases());
125         }
126 
127         return StringUtils.join(phases.iterator(), ", ");
128     }
129 }