001package org.apache.maven.artifact.resolver; 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.Iterator; 023import java.util.List; 024 025import org.apache.maven.artifact.Artifact; 026import org.apache.maven.artifact.repository.ArtifactRepository; 027import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; 028 029/** 030 * Base class for artifact resolution exceptions. 031 * 032 * @author <a href="mailto:brett@apache.org">Brett Porter</a> 033 */ 034public class AbstractArtifactResolutionException 035 extends Exception 036{ 037 private String groupId; 038 039 private String artifactId; 040 041 private String version; 042 043 private String type; 044 045 private String classifier; 046 047 private Artifact artifact; 048 049 private List<ArtifactRepository> remoteRepositories; 050 051 private final String originalMessage; 052 053 private final String path; 054 055 static final String LS = System.getProperty( "line.separator" ); 056 057 @SuppressWarnings( "checkstyle:parameternumber" ) 058 protected AbstractArtifactResolutionException( String message, 059 String groupId, 060 String artifactId, 061 String version, 062 String type, 063 String classifier, 064 List<ArtifactRepository> remoteRepositories, 065 List<String> path ) 066 { 067 this( message, groupId, artifactId, version, type, classifier, remoteRepositories, path, null ); 068 } 069 070 @SuppressWarnings( "checkstyle:parameternumber" ) 071 protected AbstractArtifactResolutionException( String message, 072 String groupId, 073 String artifactId, 074 String version, 075 String type, 076 String classifier, 077 List<ArtifactRepository> remoteRepositories, 078 List<String> path, 079 Throwable t ) 080 { 081 super( constructMessageBase( message, groupId, artifactId, version, type, remoteRepositories, path ), t ); 082 083 this.originalMessage = message; 084 this.groupId = groupId; 085 this.artifactId = artifactId; 086 this.type = type; 087 this.classifier = classifier; 088 this.version = version; 089 this.remoteRepositories = remoteRepositories; 090 this.path = constructArtifactPath( path, "" ); 091 } 092 093 protected AbstractArtifactResolutionException( String message, 094 Artifact artifact ) 095 { 096 this( message, artifact, null ); 097 } 098 099 protected AbstractArtifactResolutionException( String message, 100 Artifact artifact, 101 List<ArtifactRepository> remoteRepositories ) 102 { 103 this( message, artifact, remoteRepositories, null ); 104 } 105 106 protected AbstractArtifactResolutionException( String message, 107 Artifact artifact, 108 List<ArtifactRepository> remoteRepositories, 109 Throwable t ) 110 { 111 this( message, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getType(), 112 artifact.getClassifier(), remoteRepositories, artifact.getDependencyTrail(), t ); 113 this.artifact = artifact; 114 } 115 116 public Artifact getArtifact() 117 { 118 return artifact; 119 } 120 121 public String getGroupId() 122 { 123 return groupId; 124 } 125 126 public String getArtifactId() 127 { 128 return artifactId; 129 } 130 131 public String getVersion() 132 { 133 return version; 134 } 135 136 public String getType() 137 { 138 return type; 139 } 140 141 /** @return the classifier */ 142 public String getClassifier() 143 { 144 return this.classifier; 145 } 146 147 /** @return the path */ 148 public String getPath() 149 { 150 return this.path; 151 } 152 153 public List<ArtifactRepository> getRemoteRepositories() 154 { 155 return remoteRepositories; 156 } 157 158 public String getOriginalMessage() 159 { 160 return originalMessage; 161 } 162 163 protected static String constructArtifactPath( List<String> path, 164 String indentation ) 165 { 166 StringBuilder sb = new StringBuilder(); 167 168 if ( path != null ) 169 { 170 sb.append( LS ); 171 sb.append( indentation ); 172 sb.append( "Path to dependency: " ); 173 sb.append( LS ); 174 int num = 1; 175 for ( Iterator<String> i = path.iterator(); i.hasNext(); num++ ) 176 { 177 sb.append( indentation ); 178 sb.append( "\t" ); 179 sb.append( num ); 180 sb.append( ") " ); 181 sb.append( i.next() ); 182 sb.append( LS ); 183 } 184 } 185 186 return sb.toString(); 187 } 188 189 private static String constructMessageBase( String message, 190 String groupId, 191 String artifactId, 192 String version, 193 String type, 194 List<ArtifactRepository> remoteRepositories, 195 List<String> path ) 196 { 197 StringBuilder sb = new StringBuilder(); 198 199 sb.append( message ); 200 201 if ( message == null || !message.contains( "from the specified remote repositories:" ) ) 202 { 203 sb.append( LS ); 204 sb.append( " " ).append( groupId ).append( ":" ).append( artifactId ).append( ":" ).append( type ).append( 205 ":" ).append( version ); 206 sb.append( LS ); 207 if ( remoteRepositories != null ) 208 { 209 sb.append( LS ); 210 sb.append( "from the specified remote repositories:" ); 211 sb.append( LS ).append( " " ); 212 213 if ( remoteRepositories.isEmpty() ) 214 { 215 sb.append( "(none)" ); 216 } 217 218 for ( Iterator<ArtifactRepository> i = remoteRepositories.iterator(); i.hasNext(); ) 219 { 220 ArtifactRepository remoteRepository = i.next(); 221 222 sb.append( remoteRepository.getId() ); 223 sb.append( " (" ); 224 sb.append( remoteRepository.getUrl() ); 225 226 ArtifactRepositoryPolicy releases = remoteRepository.getReleases(); 227 if ( releases != null ) 228 { 229 sb.append( ", releases=" ).append( releases.isEnabled() ); 230 } 231 232 ArtifactRepositoryPolicy snapshots = remoteRepository.getSnapshots(); 233 if ( snapshots != null ) 234 { 235 sb.append( ", snapshots=" ).append( snapshots.isEnabled() ); 236 } 237 238 sb.append( ")" ); 239 if ( i.hasNext() ) 240 { 241 sb.append( "," ).append( LS ).append( " " ); 242 } 243 } 244 } 245 246 sb.append( constructArtifactPath( path, "" ) ); 247 sb.append( LS ); 248 } 249 250 return sb.toString(); 251 } 252 253 @SuppressWarnings( "checkstyle:parameternumber" ) 254 protected static String constructMissingArtifactMessage( String message, 255 String indentation, 256 String groupId, 257 String artifactId, 258 String version, 259 String type, 260 String classifier, 261 String downloadUrl, 262 List<String> path ) 263 { 264 StringBuilder sb = new StringBuilder( message ); 265 266 if ( !"pom".equals( type ) ) 267 { 268 if ( downloadUrl != null ) 269 { 270 sb.append( LS ); 271 sb.append( LS ); 272 sb.append( indentation ); 273 sb.append( "Try downloading the file manually from: " ); 274 sb.append( LS ); 275 sb.append( indentation ); 276 sb.append( " " ); 277 sb.append( downloadUrl ); 278 } 279 else 280 { 281 sb.append( LS ); 282 sb.append( LS ); 283 sb.append( indentation ); 284 sb.append( "Try downloading the file manually from the project website." ); 285 } 286 287 sb.append( LS ); 288 sb.append( LS ); 289 sb.append( indentation ); 290 sb.append( "Then, install it using the command: " ); 291 sb.append( LS ); 292 sb.append( indentation ); 293 sb.append( " mvn install:install-file -DgroupId=" ); 294 sb.append( groupId ); 295 sb.append( " -DartifactId=" ); 296 sb.append( artifactId ); 297 sb.append( " -Dversion=" ); 298 sb.append( version ); 299 300 //insert classifier only if it was used in the artifact 301 if ( classifier != null && !classifier.equals( "" ) ) 302 { 303 sb.append( " -Dclassifier=" ); 304 sb.append( classifier ); 305 } 306 sb.append( " -Dpackaging=" ); 307 sb.append( type ); 308 sb.append( " -Dfile=/path/to/file" ); 309 sb.append( LS ); 310 311 // If people want to deploy it 312 sb.append( LS ); 313 sb.append( indentation ); 314 sb.append( "Alternatively, if you host your own repository you can deploy the file there: " ); 315 sb.append( LS ); 316 sb.append( indentation ); 317 sb.append( " mvn deploy:deploy-file -DgroupId=" ); 318 sb.append( groupId ); 319 sb.append( " -DartifactId=" ); 320 sb.append( artifactId ); 321 sb.append( " -Dversion=" ); 322 sb.append( version ); 323 324 //insert classifier only if it was used in the artifact 325 if ( classifier != null && !classifier.equals( "" ) ) 326 { 327 sb.append( " -Dclassifier=" ); 328 sb.append( classifier ); 329 } 330 sb.append( " -Dpackaging=" ); 331 sb.append( type ); 332 sb.append( " -Dfile=/path/to/file" ); 333 sb.append( " -Durl=[url] -DrepositoryId=[id]" ); 334 sb.append( LS ); 335 } 336 337 sb.append( constructArtifactPath( path, indentation ) ); 338 sb.append( LS ); 339 340 return sb.toString(); 341 } 342 343 public String getArtifactPath() 344 { 345 return path; 346 } 347}