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.eclipse.aether.collection;
20  
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.Iterator;
24  import java.util.LinkedHashSet;
25  import java.util.List;
26  
27  import org.eclipse.aether.RepositoryException;
28  import org.eclipse.aether.artifact.Artifact;
29  import org.eclipse.aether.graph.DependencyNode;
30  import org.eclipse.aether.version.VersionConstraint;
31  
32  /**
33   * Thrown in case of an unsolvable conflict between different version constraints for a dependency.
34   */
35  public class UnsolvableVersionConflictException extends RepositoryException {
36  
37      private final transient Collection<String> versions;
38  
39      private final transient Collection<? extends List<? extends DependencyNode>> paths;
40  
41      /**
42       * Creates a new exception with the specified paths to conflicting nodes in the dependency graph.
43       *
44       * @param paths The paths to the dependency nodes that participate in the version conflict, may be {@code null}.
45       */
46      public UnsolvableVersionConflictException(Collection<? extends List<? extends DependencyNode>> paths) {
47          super("Could not resolve version conflict among " + toPaths(paths));
48          if (paths == null) {
49              this.paths = Collections.emptyList();
50              this.versions = Collections.emptyList();
51          } else {
52              this.paths = paths;
53              this.versions = new LinkedHashSet<>();
54              for (List<? extends DependencyNode> path : paths) {
55                  VersionConstraint constraint = path.get(path.size() - 1).getVersionConstraint();
56                  if (constraint != null && constraint.getRange() != null) {
57                      versions.add(constraint.toString());
58                  }
59              }
60          }
61      }
62  
63      private static String toPaths(Collection<? extends List<? extends DependencyNode>> paths) {
64          String result = "";
65  
66          if (paths != null) {
67              Collection<String> strings = new LinkedHashSet<>();
68  
69              for (List<? extends DependencyNode> path : paths) {
70                  strings.add(toPath(path));
71              }
72  
73              result = strings.toString();
74          }
75  
76          return result;
77      }
78  
79      private static String toPath(List<? extends DependencyNode> path) {
80          StringBuilder buffer = new StringBuilder(256);
81  
82          for (Iterator<? extends DependencyNode> it = path.iterator(); it.hasNext(); ) {
83              DependencyNode node = it.next();
84              if (node.getDependency() == null) {
85                  continue;
86              }
87  
88              Artifact artifact = node.getDependency().getArtifact();
89              buffer.append(artifact.getGroupId());
90              buffer.append(':').append(artifact.getArtifactId());
91              buffer.append(':').append(artifact.getExtension());
92              if (!artifact.getClassifier().isEmpty()) {
93                  buffer.append(':').append(artifact.getClassifier());
94              }
95              buffer.append(':').append(node.getVersionConstraint());
96  
97              if (it.hasNext()) {
98                  buffer.append(" -> ");
99              }
100         }
101 
102         return buffer.toString();
103     }
104 
105     /**
106      * Gets the paths leading to the conflicting dependencies.
107      *
108      * @return The (read-only) paths leading to the conflicting dependencies, never {@code null}.
109      */
110     public Collection<? extends List<? extends DependencyNode>> getPaths() {
111         return paths;
112     }
113 
114     /**
115      * Gets the conflicting version constraints of the dependency.
116      *
117      * @return The (read-only) conflicting version constraints, never {@code null}.
118      */
119     public Collection<String> getVersions() {
120         return versions;
121     }
122 }