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  import org.apache.maven.plugin.descriptor.MojoDescriptor;
36  
37  //TODO: lifecycles being executed
38  //TODO: what runs in each phase
39  //TODO: plugins that need downloading
40  //TODO: project dependencies that need downloading
41  //TODO: unfortunately the plugins need to be downloaded in order to get the plugin.xml file. need to externalize this
42  //      from the plugin archive.
43  //TODO: this will be the class that people get in IDEs to modify
44  
45  public class MavenExecutionPlan
46      implements Iterable<ExecutionPlanItem>
47  {
48  
49      /*
50         At the moment, this class is totally immutable, and this is in line with thoughts about the
51         pre-calculated execution plan that stays the same during the execution.
52  
53         If deciding to add mutable state to this class, it should be at least considered to
54         separate this into a separate mutable structure.
55  
56       */
57  
58      private final List<ExecutionPlanItem> planItem;
59  
60      private final Map<String, ExecutionPlanItem> lastMojoExecutionForAllPhases;
61  
62      final List<String> phasesInExecutionPlan;
63  
64      public MavenExecutionPlan( List<ExecutionPlanItem> planItem, DefaultLifecycles defaultLifecycles )
65      {
66          this.planItem = planItem;
67  
68          lastMojoExecutionForAllPhases = new LinkedHashMap<String, ExecutionPlanItem>();
69  
70          LinkedHashSet<String> totalPhaseSet = new LinkedHashSet<String>();
71          if ( defaultLifecycles != null )
72          {
73              for ( String phase : getDistinctPhasesInOrderOfExecutionPlanAppearance( planItem ) )
74              {
75                  final Lifecycle lifecycle = defaultLifecycles.get( phase );
76                  if ( lifecycle != null )
77                  {
78                      totalPhaseSet.addAll( lifecycle.getPhases() );
79                  }
80              }
81          }
82          this.phasesInExecutionPlan = new ArrayList<String>( totalPhaseSet );
83  
84          Map<String, ExecutionPlanItem> lastInExistingPhases = new HashMap<String, ExecutionPlanItem>();
85          for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
86          {
87              lastInExistingPhases.put( executionPlanItem.getLifecyclePhase(), executionPlanItem );
88          }
89  
90          ExecutionPlanItem lastSeenExecutionPlanItem = null;
91  
92          for ( String phase : totalPhaseSet )
93          {
94              ExecutionPlanItem forThisPhase = lastInExistingPhases.get( phase );
95              if ( forThisPhase != null )
96              {
97                  lastSeenExecutionPlanItem = forThisPhase;
98              }
99  
100             lastMojoExecutionForAllPhases.put( phase, lastSeenExecutionPlanItem );
101         }
102     }
103 
104     public Iterator<ExecutionPlanItem> iterator()
105     {
106         return getExecutionPlanItems().iterator();
107     }
108 
109     /**
110      * Returns the last ExecutionPlanItem in the supplied phase. If no items are in the specified phase,
111      * the closest executionPlanItem from an earlier phase item will be returned.
112      *
113      * @param requestedPhase the requested phase
114      *                       The execution plan item
115      * @return The ExecutionPlanItem or null if none can be found
116      */
117     public ExecutionPlanItem findLastInPhase( String requestedPhase )
118     {
119         return lastMojoExecutionForAllPhases.get( requestedPhase );
120     }
121 
122     private List<ExecutionPlanItem> getExecutionPlanItems()
123     {
124         return planItem;
125     }
126 
127     private static Iterable<String> getDistinctPhasesInOrderOfExecutionPlanAppearance(
128         List<ExecutionPlanItem> planItems )
129     {
130         LinkedHashSet<String> result = new LinkedHashSet<String>();
131         for ( ExecutionPlanItem executionPlanItem : planItems )
132         {
133             final String phase = executionPlanItem.getLifecyclePhase();
134             if ( !result.contains( phase ) )
135             {
136                 result.add( phase );
137             }
138         }
139         return result;
140     }
141 
142     public void forceAllComplete()
143     {
144         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
145         {
146             executionPlanItem.forceComplete();
147         }
148     }
149 
150     public void waitUntilAllDone()
151         throws InterruptedException
152     {
153         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
154         {
155             executionPlanItem.waitUntilDone();
156         }
157     }
158 
159     public boolean containsPhase( String phase )
160     {
161         return phasesInExecutionPlan.contains( phase );
162     }
163 
164     public List<MojoExecution> getMojoExecutions()
165     {
166         List<MojoExecution> result = new ArrayList<MojoExecution>();
167         for ( ExecutionPlanItem executionPlanItem : planItem )
168         {
169             result.add( executionPlanItem.getMojoExecution() );
170         }
171         return result;
172     }
173 
174     /**
175      * Get set of plugins having a goal/mojo used but not marked @threadSafe
176      *
177      * @return the set of plugins (without info on which goal is concerned)
178      */
179     public Set<Plugin> getNonThreadSafePlugins()
180     {
181         Set<Plugin> plugins = new HashSet<Plugin>();
182         for ( ExecutionPlanItem executionPlanItem : planItem )
183         {
184             final MojoExecution mojoExecution = executionPlanItem.getMojoExecution();
185             if ( !mojoExecution.getMojoDescriptor().isThreadSafe() )
186             {
187                 plugins.add( mojoExecution.getPlugin() );
188             }
189         }
190         return plugins;
191     }
192 
193     /**
194      * Get set of mojos used but not marked @threadSafe
195      *
196      * @return the set of mojo descriptors
197      */
198     public Set<MojoDescriptor> getNonThreadSafeMojos()
199     {
200         Set<MojoDescriptor> mojos = new HashSet<MojoDescriptor>();
201         for ( ExecutionPlanItem executionPlanItem : planItem )
202         {
203             final MojoExecution mojoExecution = executionPlanItem.getMojoExecution();
204             if ( !mojoExecution.getMojoDescriptor().isThreadSafe() )
205             {
206                 mojos.add( mojoExecution.getMojoDescriptor() );
207             }
208         }
209         return mojos;
210     }
211 
212     // Used by m2e but will be removed, really.
213     @Deprecated
214     public List<MojoExecution> getExecutions()
215     {
216         return getMojoExecutions();
217     }
218 
219     public int size()
220     {
221         return planItem.size();
222     }
223 
224 }