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      @Override
51      public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
52      {
53          Build build = model.getBuild();
54          if ( build != null )
55          {
56              List<Plugin> plugins = build.getPlugins();
57              Map<Object, Plugin> normalized = new LinkedHashMap<Object, Plugin>( plugins.size() * 2 );
58  
59              for ( Plugin plugin : plugins )
60              {
61                  Object key = plugin.getKey();
62                  Plugin first = normalized.get( key );
63                  if ( first != null )
64                  {
65                      merger.mergePlugin( plugin, first );
66                  }
67                  normalized.put( key, plugin );
68              }
69  
70              if ( plugins.size() != normalized.size() )
71              {
72                  build.setPlugins( new ArrayList<Plugin>( normalized.values() ) );
73              }
74          }
75  
76          /*
77           * NOTE: This is primarily to keep backward-compat with Maven 2.x which did not validate that dependencies are
78           * unique within a single POM. Upon multiple declarations, 2.x just kept the last one but retained the order of
79           * the first occurrence. So when we're in lenient/compat mode, we have to deal with such broken POMs and mimic
80           * the way 2.x works. When we're in strict mode, the removal of duplicates just saves other merging steps from
81           * aftereffects and bogus error messages.
82           */
83          List<Dependency> dependencies = model.getDependencies();
84          Map<String, Dependency> normalized = new LinkedHashMap<String, Dependency>( dependencies.size() * 2 );
85  
86          for ( Dependency dependency : dependencies )
87          {
88              normalized.put( dependency.getManagementKey(), dependency );
89          }
90  
91          if ( dependencies.size() != normalized.size() )
92          {
93              model.setDependencies( new ArrayList<Dependency>( normalized.values() ) );
94          }
95      }
96  
97      protected static class DuplicateMerger
98          extends MavenModelMerger
99      {
100 
101         public void mergePlugin( Plugin target, Plugin source )
102         {
103             super.mergePlugin( target, source, false, Collections.emptyMap() );
104         }
105 
106     }
107 
108     @Override
109     public void injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
110     {
111         injectDependencyDefaults( model.getDependencies() );
112 
113         Build build = model.getBuild();
114         if ( build != null )
115         {
116             for ( Plugin plugin : build.getPlugins() )
117             {
118                 injectDependencyDefaults( plugin.getDependencies() );
119             }
120         }
121     }
122 
123     private void injectDependencyDefaults( List<Dependency> dependencies )
124     {
125         for ( Dependency dependency : dependencies )
126         {
127             if ( StringUtils.isEmpty( dependency.getScope() ) )
128             {
129                 // we cannot set this directly in the MDO due to the interactions with dependency management
130                 dependency.setScope( "compile" );
131             }
132         }
133     }
134 
135 }