001 package org.apache.maven.lifecycle;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.util.ArrayList;
023 import java.util.HashMap;
024 import java.util.HashSet;
025 import java.util.Iterator;
026 import java.util.LinkedHashMap;
027 import java.util.LinkedHashSet;
028 import java.util.List;
029 import java.util.Map;
030 import java.util.Set;
031
032 import org.apache.maven.lifecycle.internal.ExecutionPlanItem;
033 import org.apache.maven.model.Plugin;
034 import org.apache.maven.plugin.MojoExecution;
035
036 //TODO: lifecycles being executed
037 //TODO: what runs in each phase
038 //TODO: plugins that need downloading
039 //TODO: project dependencies that need downloading
040 //TODO: unfortunately the plugins need to be downloaded in order to get the plugin.xml file. need to externalize this
041 // from the plugin archive.
042 //TODO: this will be the class that people get in IDEs to modify
043
044 public class MavenExecutionPlan
045 implements Iterable<ExecutionPlanItem>
046 {
047
048 /*
049 At the moment, this class is totally immutable, and this is in line with thoughts about the
050 pre-calculated execution plan that stays the same during the execution.
051
052 If deciding to add mutable state to this class, it should be at least considered to
053 separate this into a separate mutable structure.
054
055 */
056
057 private final List<ExecutionPlanItem> planItem;
058
059 private final Map<String, ExecutionPlanItem> lastMojoExecutionForAllPhases;
060
061 final List<String> phasesInExecutionPlan;
062
063 public MavenExecutionPlan( List<ExecutionPlanItem> planItem, DefaultLifecycles defaultLifecycles )
064 {
065 this.planItem = planItem;
066
067 lastMojoExecutionForAllPhases = new LinkedHashMap<String, ExecutionPlanItem>();
068
069 LinkedHashSet<String> totalPhaseSet = new LinkedHashSet<String>();
070 if ( defaultLifecycles != null )
071 {
072 for ( String phase : getDistinctPhasesInOrderOfExecutionPlanAppearance( planItem ) )
073 {
074 final Lifecycle lifecycle = defaultLifecycles.get( phase );
075 if ( lifecycle != null )
076 {
077 totalPhaseSet.addAll( lifecycle.getPhases() );
078 }
079 }
080 }
081 this.phasesInExecutionPlan = new ArrayList<String>( totalPhaseSet );
082
083 Map<String, ExecutionPlanItem> lastInExistingPhases = new HashMap<String, ExecutionPlanItem>();
084 for ( ExecutionPlanItem executionPlanItem : getExecutionPlanItems() )
085 {
086 lastInExistingPhases.put( executionPlanItem.getLifecyclePhase(), executionPlanItem );
087 }
088
089 ExecutionPlanItem lastSeenExecutionPlanItem = null;
090
091 for ( String phase : totalPhaseSet )
092 {
093 ExecutionPlanItem forThisPhase = lastInExistingPhases.get( phase );
094 if ( forThisPhase != null )
095 {
096 lastSeenExecutionPlanItem = forThisPhase;
097 }
098
099 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 }