View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.model.composition;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.util.*;
25  
26  import org.apache.maven.api.model.Dependency;
27  import org.apache.maven.api.model.DependencyManagement;
28  import org.apache.maven.api.model.Exclusion;
29  import org.apache.maven.api.model.Model;
30  import org.apache.maven.model.building.ModelBuildingRequest;
31  import org.apache.maven.model.building.ModelProblem;
32  import org.apache.maven.model.building.ModelProblemCollector;
33  import org.apache.maven.model.building.ModelProblemCollectorRequest;
34  
35  /**
36   * Handles the import of dependency management from other models into the target model.
37   *
38   */
39  @Named
40  @Singleton
41  public class DefaultDependencyManagementImporter implements DependencyManagementImporter {
42  
43      @Override
44      public Model importManagement(
45              Model target,
46              List<? extends DependencyManagement> sources,
47              ModelBuildingRequest request,
48              ModelProblemCollector problems) {
49          if (sources != null && !sources.isEmpty()) {
50              Map<String, Dependency> dependencies = new LinkedHashMap<>();
51  
52              DependencyManagement depMgmt = target.getDependencyManagement();
53  
54              if (depMgmt != null) {
55                  for (Dependency dependency : depMgmt.getDependencies()) {
56                      dependencies.put(dependency.getManagementKey(), dependency);
57                  }
58              } else {
59                  depMgmt = DependencyManagement.newInstance();
60              }
61  
62              Set<String> directDependencies = new HashSet<>(dependencies.keySet());
63  
64              for (DependencyManagement source : sources) {
65                  for (Dependency dependency : source.getDependencies()) {
66                      String key = dependency.getManagementKey();
67                      Dependency present = dependencies.putIfAbsent(key, dependency);
68                      if (present != null && !equals(dependency, present) && !directDependencies.contains(key)) {
69                          // TODO: https://issues.apache.org/jira/browse/MNG-8004
70                          problems.add(new ModelProblemCollectorRequest(
71                                          ModelProblem.Severity.WARNING, ModelProblem.Version.V40)
72                                  .setMessage("Ignored POM import for: " + toString(dependency) + " as already imported "
73                                          + toString(present) + ".  Add a the conflicting managed dependency directly "
74                                          + "to the dependencyManagement section of the POM."));
75                      }
76                  }
77              }
78  
79              return target.withDependencyManagement(depMgmt.withDependencies(dependencies.values()));
80          }
81          return target;
82      }
83  
84      private String toString(Dependency dependency) {
85          StringBuilder stringBuilder = new StringBuilder();
86          stringBuilder
87                  .append(dependency.getGroupId())
88                  .append(":")
89                  .append(dependency.getArtifactId())
90                  .append(":")
91                  .append(dependency.getType());
92          if (dependency.getClassifier() != null && !dependency.getClassifier().isEmpty()) {
93              stringBuilder.append(":").append(dependency.getClassifier());
94          }
95          stringBuilder
96                  .append(":")
97                  .append(dependency.getVersion())
98                  .append("@")
99                  .append(dependency.getScope() == null ? "compile" : dependency.getScope());
100         if (dependency.isOptional()) {
101             stringBuilder.append("[optional]");
102         }
103         if (!dependency.getExclusions().isEmpty()) {
104             stringBuilder.append("[").append(dependency.getExclusions().size()).append(" exclusions]");
105         }
106         return stringBuilder.toString();
107     }
108 
109     private boolean equals(Dependency d1, Dependency d2) {
110         return Objects.equals(d1.getGroupId(), d2.getGroupId())
111                 && Objects.equals(d1.getArtifactId(), d2.getArtifactId())
112                 && Objects.equals(d1.getVersion(), d2.getVersion())
113                 && Objects.equals(d1.getType(), d2.getType())
114                 && Objects.equals(d1.getClassifier(), d2.getClassifier())
115                 && Objects.equals(d1.getScope(), d2.getScope())
116                 && Objects.equals(d1.getSystemPath(), d2.getSystemPath())
117                 && Objects.equals(d1.getOptional(), d2.getOptional())
118                 && equals(d1.getExclusions(), d2.getExclusions());
119     }
120 
121     private boolean equals(Collection<Exclusion> ce1, Collection<Exclusion> ce2) {
122         if (ce1.size() == ce2.size()) {
123             Iterator<Exclusion> i1 = ce1.iterator();
124             Iterator<Exclusion> i2 = ce2.iterator();
125             while (i1.hasNext() && i2.hasNext()) {
126                 if (!equals(i1.next(), i2.next())) {
127                     return false;
128                 }
129             }
130             return !i1.hasNext() && !i2.hasNext();
131         }
132         return false;
133     }
134 
135     private boolean equals(Exclusion e1, Exclusion e2) {
136         return Objects.equals(e1.getGroupId(), e2.getGroupId())
137                 && Objects.equals(e1.getArtifactId(), e2.getArtifactId());
138     }
139 }