View Javadoc

1   package org.apache.maven.lifecycle;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.HashMap;
24  import java.util.HashSet;
25  import java.util.Iterator;
26  import java.util.LinkedHashMap;
27  import java.util.LinkedHashSet;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.Set;
31  
32  import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
33  import org.apache.maven.model.Plugin;
34  import org.apache.maven.plugin.MojoExecution;
35  
36  //TODO: lifecycles being executed
37  //TODO: what runs in each phase
38  //TODO: plugins that need downloading
39  //TODO: project dependencies that need downloading
40  //TODO: unfortunately the plugins need to be downloaded in order to get the plugin.xml file. need to externalize this
41  //      from the plugin archive.
42  //TODO: this will be the class that people get in IDEs to modify
43  
44  public class MavenExecutionPlan
45      implements Iterable<ExecutionPlanItem>
46  {
47  
48      /*
49         At the moment, this class is totally immutable, and this is in line with thoughts about the
50         pre-calculated execution plan that stays the same during the execution.
51  
52         If deciding to add mutable state to this class, it should be at least considered to
53         separate this into a separate mutable structure.
54  
55       */
56  
57      private final List<ExecutionPlanItem> planItem;
58  
59      private final Map<String, ExecutionPlanItem> lastMojoExecutionForAllPhases;
60  
61      final List<String> phasesInExecutionPlan;
62  
63      public MavenExecutionPlan( List<ExecutionPlanItem> planItem, DefaultLifecycles defaultLifecycles )
64      {
65          this.planItem = planItem;
66  
67          lastMojoExecutionForAllPhases = new LinkedHashMap<String, ExecutionPlanItem>();
68  
69          LinkedHashSet<String> totalPhaseSet = new LinkedHashSet<String>();
70          if ( defaultLifecycles != null )
71          {
72              for ( String phase : getDistinctPhasesInOrderOfExecutionPlanAppearance( planItem ) )
73              {
74                  final Lifecycle lifecycle = defaultLifecycles.get( phase );
75                  if ( lifecycle != null )
76                  {
77                      totalPhaseSet.addAll( lifecycle.getPhases() );
78                  }
79              }
80          }
81          this.phasesInExecutionPlan = new ArrayList<String>( totalPhaseSet );
82  
83          Map<String, ExecutionPlanItem> lastInExistingPhases = new HashMap<String, ExecutionPlanItem>();
84          for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
85          {
86              lastInExistingPhases.put( executionPlanItem.getLifecyclePhase(), executionPlanItem );
87          }
88  
89          ExecutionPlanItem lastSeenExecutionPlanItem = null;
90  
91          for ( String phase : totalPhaseSet )
92          {
93              ExecutionPlanItem forThisPhase = lastInExistingPhases.get( phase );
94              if ( forThisPhase != null )
95              {
96                  lastSeenExecutionPlanItem = forThisPhase;
97              }
98  
99              lastMojoExecutionForAllPhases.put( phase, lastSeenExecutionPlanItem );
100         }
101     }
102 
103     public Iterator<ExecutionPlanItem> iterator()
104     {
105         return getExecutionPlanItems().iterator();
106     }
107 
108     /**
109      * Returns the last ExecutionPlanItem in the supplied phase. If no items are in the specified phase,
110      * the closest executionPlanItem from an earlier phase item will be returned.
111      *
112      * @param requestedPhase the requested phase
113      *                       The execution plan item
114      * @return The ExecutionPlanItem or null if none can be found
115      */
116     public ExecutionPlanItem findLastInPhase( String requestedPhase )
117     {
118         return lastMojoExecutionForAllPhases.get( requestedPhase );
119     }
120 
121     private List<ExecutionPlanItem> getExecutionPlanItems()
122     {
123         return planItem;
124     }
125 
126     private static Iterable<String> getDistinctPhasesInOrderOfExecutionPlanAppearance(
127         List<ExecutionPlanItem> planItems )
128     {
129         LinkedHashSet<String> result = new LinkedHashSet<String>();
130         for ( ExecutionPlanItem executionPlanItem : planItems )
131         {
132             final String phase = executionPlanItem.getLifecyclePhase();
133             if ( !result.contains( phase ) )
134             {
135                 result.add( phase );
136             }
137         }
138         return result;
139     }
140 
141     public void forceAllComplete()
142     {
143         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
144         {
145             executionPlanItem.forceComplete();
146         }
147     }
148 
149     public void waitUntilAllDone()
150         throws InterruptedException
151     {
152         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
153         {
154             executionPlanItem.waitUntilDone();
155         }
156     }
157 
158     public boolean containsPhase( String phase )
159     {
160         return phasesInExecutionPlan.contains( phase );
161     }
162 
163     public List<MojoExecution> getMojoExecutions()
164     {
165         List<MojoExecution> result = new ArrayList<MojoExecution>();
166         for ( ExecutionPlanItem executionPlanItem : planItem )
167         {
168             result.add( executionPlanItem.getMojoExecution() );
169         }
170         return result;
171     }
172 
173 
174     public Set<Plugin> getNonThreadSafePlugins()
175     {
176         Set<Plugin> plugins = new HashSet<Plugin>();
177         for ( ExecutionPlanItem executionPlanItem : planItem )
178         {
179             final MojoExecution mojoExecution = executionPlanItem.getMojoExecution();
180             if ( !mojoExecution.getMojoDescriptor().isThreadSafe() )
181             {
182                 plugins.add( mojoExecution.getPlugin() );
183             }
184         }
185         return plugins;
186     }
187 
188     // Used by m2e but will be removed, really.
189     @Deprecated
190     public List<MojoExecution> getExecutions()
191     {
192         return getMojoExecutions();
193     }
194 
195     public int size()
196     {
197         return planItem.size();
198     }
199 
200 }