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  
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          ExecutionPlanItem forThisPhase;
92  
93          for ( String phase : totalPhaseSet )
94          {
95              forThisPhase = lastInExistingPhases.get( phase );
96              if ( forThisPhase != null )
97              {
98                  lastSeenExecutionPlanItem = forThisPhase;
99              }
100             lastMojoExecutionForAllPhases.put( phase, lastSeenExecutionPlanItem );
101 
102         }
103     }
104 
105     public Iterator<ExecutionPlanItem> iterator()
106     {
107         return getExecutionPlanItems().iterator();
108     }
109 
110     /**
111      * Returns the last ExecutionPlanItem in the supplied phase. If no items are in the specified phase,
112      * the closest executionPlanItem from an earlier phase item will be returned.
113      *
114      * @param requestedPhase the requested phase
115      *                       The execution plan item
116      * @return The ExecutionPlanItem or null if none can be found
117      */
118     public ExecutionPlanItem findLastInPhase( String requestedPhase )
119     {
120         return lastMojoExecutionForAllPhases.get( requestedPhase );
121     }
122 
123     private List<ExecutionPlanItem> getExecutionPlanItems()
124     {
125         return planItem;
126     }
127 
128 
129     private static Iterable<String> getDistinctPhasesInOrderOfExecutionPlanAppearance(
130         List<ExecutionPlanItem> planItems )
131     {
132         LinkedHashSet<String> result = new LinkedHashSet<String>();
133         for ( ExecutionPlanItem executionPlanItem : planItems )
134         {
135             final String phase = executionPlanItem.getLifecyclePhase();
136             if ( !result.contains( phase ) )
137             {
138                 result.add( phase );
139             }
140         }
141         return result;
142     }
143 
144     public void forceAllComplete()
145     {
146         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
147         {
148             executionPlanItem.forceComplete();
149         }
150     }
151 
152     public void waitUntilAllDone()
153         throws InterruptedException
154     {
155         for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
156         {
157             executionPlanItem.waitUntilDone();
158         }
159     }
160 
161     public boolean containsPhase( String phase )
162     {
163         return phasesInExecutionPlan.contains( phase );
164     }
165 
166     public List<MojoExecution> getMojoExecutions()
167     {
168         List<MojoExecution> result = new ArrayList<MojoExecution>();
169         for ( ExecutionPlanItem executionPlanItem : planItem )
170         {
171             result.add( executionPlanItem.getMojoExecution() );
172         }
173         return result;
174     }
175 
176 
177     public Set<Plugin> getNonThreadSafePlugins()
178     {
179         Set<Plugin> plugins = new HashSet<Plugin>();
180         for ( ExecutionPlanItem executionPlanItem : planItem )
181         {
182             final MojoExecution mojoExecution = executionPlanItem.getMojoExecution();
183             if ( !mojoExecution.getMojoDescriptor().isThreadSafe() )
184             {
185                 plugins.add( mojoExecution.getPlugin() );
186             }
187         }
188         return plugins;
189     }
190 
191     // Used by m2e but will be removed, really.
192 
193     @SuppressWarnings( { "UnusedDeclaration" } )
194     @Deprecated
195     public List<MojoExecution> getExecutions()
196     {
197         return getMojoExecutions();
198     }
199 
200     public int size()
201     {
202         return planItem.size();
203     }
204 
205 }