001package org.apache.maven.project; 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 022import java.util.ArrayList; 023import java.util.Iterator; 024import java.util.LinkedHashMap; 025import java.util.List; 026import java.util.Map; 027import java.util.TreeMap; 028 029import org.apache.maven.model.Dependency; 030import org.apache.maven.model.Plugin; 031import org.apache.maven.model.PluginContainer; 032import org.apache.maven.model.PluginExecution; 033import org.apache.maven.model.Repository; 034import org.codehaus.plexus.util.xml.Xpp3Dom; 035 036/** @deprecated */ 037@Deprecated 038public final class ModelUtils 039{ 040 041 /** 042 * This should be the resulting ordering of plugins after merging: 043 * <p/> 044 * Given: 045 * <p/> 046 * parent: X -> A -> B -> D -> E 047 * child: Y -> A -> C -> D -> F 048 * <p/> 049 * Result: 050 * <p/> 051 * X -> Y -> A -> B -> C -> D -> E -> F 052 */ 053 public static void mergePluginLists( PluginContainer childContainer, PluginContainer parentContainer, 054 boolean handleAsInheritance ) 055 { 056 if ( ( childContainer == null ) || ( parentContainer == null ) ) 057 { 058 // nothing to do. 059 return; 060 } 061 062 List<Plugin> parentPlugins = parentContainer.getPlugins(); 063 064 if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() ) 065 { 066 parentPlugins = new ArrayList<>( parentPlugins ); 067 068 // If we're processing this merge as an inheritance, we have to build up a list of 069 // plugins that were considered for inheritance. 070 if ( handleAsInheritance ) 071 { 072 for ( Iterator<Plugin> it = parentPlugins.iterator(); it.hasNext(); ) 073 { 074 Plugin plugin = it.next(); 075 076 String inherited = plugin.getInherited(); 077 078 if ( ( inherited != null ) && !Boolean.valueOf( inherited ) ) 079 { 080 it.remove(); 081 } 082 } 083 } 084 085 List<Plugin> assembledPlugins = new ArrayList<>(); 086 087 Map<String, Plugin> childPlugins = childContainer.getPluginsAsMap(); 088 089 for ( Plugin parentPlugin : parentPlugins ) 090 { 091 String parentInherited = parentPlugin.getInherited(); 092 093 // only merge plugin definition from the parent if at least one 094 // of these is true: 095 // 1. we're not processing the plugins in an inheritance-based merge 096 // 2. the parent's <inherited/> flag is not set 097 // 3. the parent's <inherited/> flag is set to true 098 if ( !handleAsInheritance || ( parentInherited == null ) 099 || Boolean.valueOf( parentInherited ) ) 100 { 101 Plugin childPlugin = childPlugins.get( parentPlugin.getKey() ); 102 103 if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) ) 104 { 105 Plugin assembledPlugin = childPlugin; 106 107 mergePluginDefinitions( childPlugin, parentPlugin, handleAsInheritance ); 108 109 // fix for MNG-2221 (assembly cache was not being populated for later reference): 110 assembledPlugins.add( assembledPlugin ); 111 } 112 113 // if we're processing this as an inheritance-based merge, and 114 // the parent's <inherited/> flag is not set, then we need to 115 // clear the inherited flag in the merge result. 116 if ( handleAsInheritance && ( parentInherited == null ) ) 117 { 118 parentPlugin.unsetInheritanceApplied(); 119 } 120 } 121 122 // very important to use the parentPlugins List, rather than parentContainer.getPlugins() 123 // since this list is a local one, and may have been modified during processing. 124 List<Plugin> results = 125 ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins, childContainer.getPlugins() ); 126 127 childContainer.setPlugins( results ); 128 129 childContainer.flushPluginMap(); 130 } 131 } 132 } 133 134 public static List<Plugin> orderAfterMerge( List<Plugin> merged, List<Plugin> highPrioritySource, 135 List<Plugin> lowPrioritySource ) 136 { 137 List<Plugin> results = new ArrayList<>(); 138 139 if ( !merged.isEmpty() ) 140 { 141 results.addAll( merged ); 142 } 143 144 List<Plugin> missingFromResults = new ArrayList<>(); 145 146 List<List<Plugin>> sources = new ArrayList<>(); 147 148 sources.add( highPrioritySource ); 149 sources.add( lowPrioritySource ); 150 151 for ( List<Plugin> source : sources ) 152 { 153 for ( Plugin item : source ) 154 { 155 if ( results.contains( item ) ) 156 { 157 if ( !missingFromResults.isEmpty() ) 158 { 159 int idx = results.indexOf( item ); 160 161 if ( idx < 0 ) 162 { 163 idx = 0; 164 } 165 166 results.addAll( idx, missingFromResults ); 167 168 missingFromResults.clear(); 169 } 170 } 171 else 172 { 173 missingFromResults.add( item ); 174 } 175 } 176 177 if ( !missingFromResults.isEmpty() ) 178 { 179 results.addAll( missingFromResults ); 180 181 missingFromResults.clear(); 182 } 183 } 184 185 return results; 186 } 187 188 189 public static void mergePluginDefinitions( Plugin child, Plugin parent, boolean handleAsInheritance ) 190 { 191 if ( ( child == null ) || ( parent == null ) ) 192 { 193 // nothing to do. 194 return; 195 } 196 197 if ( parent.isExtensions() ) 198 { 199 child.setExtensions( true ); 200 } 201 202 if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) ) 203 { 204 child.setVersion( parent.getVersion() ); 205 } 206 207 Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); 208 Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); 209 210 childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); 211 212 child.setConfiguration( childConfiguration ); 213 214 child.setDependencies( mergeDependencyList( child.getDependencies(), parent.getDependencies() ) ); 215 216 // from here to the end of the method is dealing with merging of the <executions/> section. 217 String parentInherited = parent.getInherited(); 218 219 boolean parentIsInherited = ( parentInherited == null ) || Boolean.valueOf( parentInherited ); 220 221 List<PluginExecution> parentExecutions = parent.getExecutions(); 222 223 if ( ( parentExecutions != null ) && !parentExecutions.isEmpty() ) 224 { 225 List<PluginExecution> mergedExecutions = new ArrayList<>(); 226 227 Map<String, PluginExecution> assembledExecutions = new TreeMap<>(); 228 229 Map<String, PluginExecution> childExecutions = child.getExecutionsAsMap(); 230 231 for ( PluginExecution parentExecution : parentExecutions ) 232 { 233 String inherited = parentExecution.getInherited(); 234 235 boolean parentExecInherited = 236 parentIsInherited && ( ( inherited == null ) || Boolean.valueOf( inherited ) ); 237 238 if ( !handleAsInheritance || parentExecInherited ) 239 { 240 PluginExecution assembled = parentExecution; 241 242 PluginExecution childExecution = childExecutions.get( parentExecution.getId() ); 243 244 if ( childExecution != null ) 245 { 246 mergePluginExecutionDefinitions( childExecution, parentExecution ); 247 248 assembled = childExecution; 249 } 250 else if ( handleAsInheritance && ( parentInherited == null ) ) 251 { 252 parentExecution.unsetInheritanceApplied(); 253 } 254 255 assembledExecutions.put( assembled.getId(), assembled ); 256 mergedExecutions.add( assembled ); 257 } 258 } 259 260 for ( PluginExecution childExecution : child.getExecutions() ) 261 { 262 if ( !assembledExecutions.containsKey( childExecution.getId() ) ) 263 { 264 mergedExecutions.add( childExecution ); 265 } 266 } 267 268 child.setExecutions( mergedExecutions ); 269 270 child.flushExecutionMap(); 271 } 272 273 } 274 275 private static void mergePluginExecutionDefinitions( PluginExecution child, PluginExecution parent ) 276 { 277 if ( child.getPhase() == null ) 278 { 279 child.setPhase( parent.getPhase() ); 280 } 281 282 List<String> parentGoals = parent.getGoals(); 283 List<String> childGoals = child.getGoals(); 284 285 List<String> goals = new ArrayList<>(); 286 287 if ( ( childGoals != null ) && !childGoals.isEmpty() ) 288 { 289 goals.addAll( childGoals ); 290 } 291 292 if ( parentGoals != null ) 293 { 294 for ( String goal : parentGoals ) 295 { 296 if ( !goals.contains( goal ) ) 297 { 298 goals.add( goal ); 299 } 300 } 301 } 302 303 child.setGoals( goals ); 304 305 Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); 306 Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); 307 308 childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); 309 310 child.setConfiguration( childConfiguration ); 311 } 312 313 public static List<Repository> mergeRepositoryLists( List<Repository> dominant, List<Repository> recessive ) 314 { 315 List<Repository> repositories = new ArrayList<>(); 316 317 for ( Repository repository : dominant ) 318 { 319 repositories.add( repository ); 320 } 321 322 for ( Repository repository : recessive ) 323 { 324 if ( !repositories.contains( repository ) ) 325 { 326 repositories.add( repository ); 327 } 328 } 329 330 return repositories; 331 } 332 333 public static void mergeFilterLists( List<String> childFilters, List<String> parentFilters ) 334 { 335 for ( String f : parentFilters ) 336 { 337 if ( !childFilters.contains( f ) ) 338 { 339 childFilters.add( f ); 340 } 341 } 342 } 343 344 private static List<Dependency> mergeDependencyList( List<Dependency> child, List<Dependency> parent ) 345 { 346 Map<String, Dependency> depsMap = new LinkedHashMap<>(); 347 348 if ( parent != null ) 349 { 350 for ( Dependency dependency : parent ) 351 { 352 depsMap.put( dependency.getManagementKey(), dependency ); 353 } 354 } 355 356 if ( child != null ) 357 { 358 for ( Dependency dependency : child ) 359 { 360 depsMap.put( dependency.getManagementKey(), dependency ); 361 } 362 } 363 364 return new ArrayList<>( depsMap.values() ); 365 } 366 367}