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 }