001 package org.apache.maven.model.normalization;
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.Collections;
024 import java.util.LinkedHashMap;
025 import java.util.List;
026 import java.util.Map;
027
028 import org.apache.maven.model.Build;
029 import org.apache.maven.model.Dependency;
030 import org.apache.maven.model.Model;
031 import org.apache.maven.model.Plugin;
032 import org.apache.maven.model.building.ModelBuildingRequest;
033 import org.apache.maven.model.building.ModelProblemCollector;
034 import org.apache.maven.model.merge.MavenModelMerger;
035 import org.codehaus.plexus.component.annotations.Component;
036 import org.codehaus.plexus.util.StringUtils;
037
038 /**
039 * Handles normalization of a model.
040 *
041 * @author Benjamin Bentmann
042 */
043 @Component( role = ModelNormalizer.class )
044 public class DefaultModelNormalizer
045 implements ModelNormalizer
046 {
047
048 private DuplicateMerger merger = new DuplicateMerger();
049
050 public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
051 {
052 Build build = model.getBuild();
053 if ( build != null )
054 {
055 List<Plugin> plugins = build.getPlugins();
056 Map<Object, Plugin> normalized = new LinkedHashMap<Object, Plugin>( plugins.size() * 2 );
057
058 for ( Plugin plugin : plugins )
059 {
060 Object key = plugin.getKey();
061 Plugin first = normalized.get( key );
062 if ( first != null )
063 {
064 merger.mergePlugin( plugin, first );
065 }
066 normalized.put( key, plugin );
067 }
068
069 if ( plugins.size() != normalized.size() )
070 {
071 build.setPlugins( new ArrayList<Plugin>( normalized.values() ) );
072 }
073 }
074
075 /*
076 * NOTE: This is primarily to keep backward-compat with Maven 2.x which did not validate that dependencies are
077 * unique within a single POM. Upon multiple declarations, 2.x just kept the last one but retained the order of
078 * the first occurrence. So when we're in lenient/compat mode, we have to deal with such broken POMs and mimic
079 * the way 2.x works. When we're in strict mode, the removal of duplicates just saves other merging steps from
080 * aftereffects and bogus error messages.
081 */
082 List<Dependency> dependencies = model.getDependencies();
083 Map<String, Dependency> normalized = new LinkedHashMap<String, Dependency>( dependencies.size() * 2 );
084
085 for ( Dependency dependency : dependencies )
086 {
087 normalized.put( dependency.getManagementKey(), dependency );
088 }
089
090 if ( dependencies.size() != normalized.size() )
091 {
092 model.setDependencies( new ArrayList<Dependency>( normalized.values() ) );
093 }
094 }
095
096 private static class DuplicateMerger
097 extends MavenModelMerger
098 {
099
100 public void mergePlugin( Plugin target, Plugin source )
101 {
102 super.mergePlugin( target, source, false, Collections.emptyMap() );
103 }
104
105 }
106
107 public void injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
108 {
109 injectDependencyDefaults( model.getDependencies() );
110
111 Build build = model.getBuild();
112 if ( build != null )
113 {
114 for ( Plugin plugin : build.getPlugins() )
115 {
116 injectDependencyDefaults( plugin.getDependencies() );
117 }
118 }
119 }
120
121 private void injectDependencyDefaults( List<Dependency> dependencies )
122 {
123 for ( Dependency dependency : dependencies )
124 {
125 if ( StringUtils.isEmpty( dependency.getScope() ) )
126 {
127 // we cannot set this directly in the MDO due to the interactions with dependency management
128 dependency.setScope( "compile" );
129 }
130 }
131 }
132
133 }