View Javadoc
1   package org.apache.maven.model.normalization;
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.Collections;
24  import java.util.LinkedHashMap;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.maven.model.Build;
29  import org.apache.maven.model.Dependency;
30  import org.apache.maven.model.Model;
31  import org.apache.maven.model.Plugin;
32  import org.apache.maven.model.building.ModelBuildingRequest;
33  import org.apache.maven.model.building.ModelProblemCollector;
34  import org.apache.maven.model.merge.MavenModelMerger;
35  import org.codehaus.plexus.component.annotations.Component;
36  import org.codehaus.plexus.util.StringUtils;
37  
38  /**
39   * Handles normalization of a model.
40   * 
41   * @author Benjamin Bentmann
42   */
43  @Component( role = ModelNormalizer.class )
44  public class DefaultModelNormalizer
45      implements ModelNormalizer
46  {
47  
48      private DuplicateMerger merger = new DuplicateMerger();
49  
50      public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
51      {
52          Build build = model.getBuild();
53          if ( build != null )
54          {
55              List<Plugin> plugins = build.getPlugins();
56              Map<Object, Plugin> normalized = new LinkedHashMap<Object, Plugin>( plugins.size() * 2 );
57  
58              for ( Plugin plugin : plugins )
59              {
60                  Object key = plugin.getKey();
61                  Plugin first = normalized.get( key );
62                  if ( first != null )
63                  {
64                      merger.mergePlugin( plugin, first );
65                  }
66                  normalized.put( key, plugin );
67              }
68  
69              if ( plugins.size() != normalized.size() )
70              {
71                  build.setPlugins( new ArrayList<Plugin>( normalized.values() ) );
72              }
73          }
74  
75          /*
76           * NOTE: This is primarily to keep backward-compat with Maven 2.x which did not validate that dependencies are
77           * unique within a single POM. Upon multiple declarations, 2.x just kept the last one but retained the order of
78           * the first occurrence. So when we're in lenient/compat mode, we have to deal with such broken POMs and mimic
79           * the way 2.x works. When we're in strict mode, the removal of duplicates just saves other merging steps from
80           * aftereffects and bogus error messages.
81           */
82          List<Dependency> dependencies = model.getDependencies();
83          Map<String, Dependency> normalized = new LinkedHashMap<String, Dependency>( dependencies.size() * 2 );
84  
85          for ( Dependency dependency : dependencies )
86          {
87              normalized.put( dependency.getManagementKey(), dependency );
88          }
89  
90          if ( dependencies.size() != normalized.size() )
91          {
92              model.setDependencies( new ArrayList<Dependency>( normalized.values() ) );
93          }
94      }
95  
96      protected static class DuplicateMerger
97          extends MavenModelMerger
98      {
99  
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 }