001package org.eclipse.aether.collection; 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 022import java.util.Collection; 023import java.util.Collections; 024import java.util.Iterator; 025import java.util.LinkedHashSet; 026import java.util.List; 027 028import org.eclipse.aether.RepositoryException; 029import org.eclipse.aether.artifact.Artifact; 030import org.eclipse.aether.graph.DependencyNode; 031import org.eclipse.aether.version.VersionConstraint; 032 033/** 034 * Thrown in case of an unsolvable conflict between different version constraints for a dependency. 035 */ 036public class UnsolvableVersionConflictException 037 extends RepositoryException 038{ 039 040 private final transient Collection<String> versions; 041 042 private final transient Collection<? extends List<? extends DependencyNode>> paths; 043 044 /** 045 * Creates a new exception with the specified paths to conflicting nodes in the dependency graph. 046 * 047 * @param paths The paths to the dependency nodes that participate in the version conflict, may be {@code null}. 048 */ 049 public UnsolvableVersionConflictException( Collection<? extends List<? extends DependencyNode>> paths ) 050 { 051 super( "Could not resolve version conflict among " + toPaths( paths ) ); 052 if ( paths == null ) 053 { 054 this.paths = Collections.emptyList(); 055 this.versions = Collections.emptyList(); 056 } 057 else 058 { 059 this.paths = paths; 060 this.versions = new LinkedHashSet<String>(); 061 for ( List<? extends DependencyNode> path : paths ) 062 { 063 VersionConstraint constraint = path.get( path.size() - 1 ).getVersionConstraint(); 064 if ( constraint != null && constraint.getRange() != null ) 065 { 066 versions.add( constraint.toString() ); 067 } 068 } 069 } 070 } 071 072 private static String toPaths( Collection<? extends List<? extends DependencyNode>> paths ) 073 { 074 String result = ""; 075 076 if ( paths != null ) 077 { 078 Collection<String> strings = new LinkedHashSet<String>(); 079 080 for ( List<? extends DependencyNode> path : paths ) 081 { 082 strings.add( toPath( path ) ); 083 } 084 085 result = strings.toString(); 086 } 087 088 return result; 089 } 090 091 private static String toPath( List<? extends DependencyNode> path ) 092 { 093 StringBuilder buffer = new StringBuilder( 256 ); 094 095 for ( Iterator<? extends DependencyNode> it = path.iterator(); it.hasNext(); ) 096 { 097 DependencyNode node = it.next(); 098 if ( node.getDependency() == null ) 099 { 100 continue; 101 } 102 103 Artifact artifact = node.getDependency().getArtifact(); 104 buffer.append( artifact.getGroupId() ); 105 buffer.append( ':' ).append( artifact.getArtifactId() ); 106 buffer.append( ':' ).append( artifact.getExtension() ); 107 if ( artifact.getClassifier().length() > 0 ) 108 { 109 buffer.append( ':' ).append( artifact.getClassifier() ); 110 } 111 buffer.append( ':' ).append( node.getVersionConstraint() ); 112 113 if ( it.hasNext() ) 114 { 115 buffer.append( " -> " ); 116 } 117 } 118 119 return buffer.toString(); 120 } 121 122 /** 123 * Gets the paths leading to the conflicting dependencies. 124 * 125 * @return The (read-only) paths leading to the conflicting dependencies, never {@code null}. 126 */ 127 public Collection<? extends List<? extends DependencyNode>> getPaths() 128 { 129 return paths; 130 } 131 132 /** 133 * Gets the conflicting version constraints of the dependency. 134 * 135 * @return The (read-only) conflicting version constraints, never {@code null}. 136 */ 137 public Collection<String> getVersions() 138 { 139 return versions; 140 } 141 142}