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.artifact.resolver;
20  
21  import java.util.Iterator;
22  import java.util.List;
23  import org.apache.maven.artifact.Artifact;
24  import org.apache.maven.artifact.repository.ArtifactRepository;
25  import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
26  
27  /**
28   * Base class for artifact resolution exceptions.
29   *
30   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
31   */
32  public class AbstractArtifactResolutionException extends Exception {
33      private String groupId;
34  
35      private String artifactId;
36  
37      private String version;
38  
39      private String type;
40  
41      private String classifier;
42  
43      private Artifact artifact;
44  
45      private List<ArtifactRepository> remoteRepositories;
46  
47      private final String originalMessage;
48  
49      private final String path;
50  
51      static final String LS = System.lineSeparator();
52  
53      @SuppressWarnings("checkstyle:parameternumber")
54      protected AbstractArtifactResolutionException(
55              String message,
56              String groupId,
57              String artifactId,
58              String version,
59              String type,
60              String classifier,
61              List<ArtifactRepository> remoteRepositories,
62              List<String> path) {
63          this(message, groupId, artifactId, version, type, classifier, remoteRepositories, path, null);
64      }
65  
66      @SuppressWarnings("checkstyle:parameternumber")
67      protected AbstractArtifactResolutionException(
68              String message,
69              String groupId,
70              String artifactId,
71              String version,
72              String type,
73              String classifier,
74              List<ArtifactRepository> remoteRepositories,
75              List<String> path,
76              Throwable t) {
77          super(constructMessageBase(message, groupId, artifactId, version, type, remoteRepositories, path), t);
78  
79          this.originalMessage = message;
80          this.groupId = groupId;
81          this.artifactId = artifactId;
82          this.type = type;
83          this.classifier = classifier;
84          this.version = version;
85          this.remoteRepositories = remoteRepositories;
86          this.path = constructArtifactPath(path, "");
87      }
88  
89      protected AbstractArtifactResolutionException(String message, Artifact artifact) {
90          this(message, artifact, null);
91      }
92  
93      protected AbstractArtifactResolutionException(
94              String message, Artifact artifact, List<ArtifactRepository> remoteRepositories) {
95          this(message, artifact, remoteRepositories, null);
96      }
97  
98      protected AbstractArtifactResolutionException(
99              String message, Artifact artifact, List<ArtifactRepository> remoteRepositories, Throwable t) {
100         this(
101                 message,
102                 artifact.getGroupId(),
103                 artifact.getArtifactId(),
104                 artifact.getVersion(),
105                 artifact.getType(),
106                 artifact.getClassifier(),
107                 remoteRepositories,
108                 artifact.getDependencyTrail(),
109                 t);
110         this.artifact = artifact;
111     }
112 
113     public Artifact getArtifact() {
114         return artifact;
115     }
116 
117     public String getGroupId() {
118         return groupId;
119     }
120 
121     public String getArtifactId() {
122         return artifactId;
123     }
124 
125     public String getVersion() {
126         return version;
127     }
128 
129     public String getType() {
130         return type;
131     }
132 
133     /** @return the classifier */
134     public String getClassifier() {
135         return this.classifier;
136     }
137 
138     /** @return the path */
139     public String getPath() {
140         return this.path;
141     }
142 
143     public List<ArtifactRepository> getRemoteRepositories() {
144         return remoteRepositories;
145     }
146 
147     public String getOriginalMessage() {
148         return originalMessage;
149     }
150 
151     protected static String constructArtifactPath(List<String> path, String indentation) {
152         StringBuilder sb = new StringBuilder();
153 
154         if (path != null) {
155             sb.append(LS);
156             sb.append(indentation);
157             sb.append("Path to dependency: ");
158             sb.append(LS);
159             int num = 1;
160             for (Iterator<String> i = path.iterator(); i.hasNext(); num++) {
161                 sb.append(indentation);
162                 sb.append('\t');
163                 sb.append(num);
164                 sb.append(") ");
165                 sb.append(i.next());
166                 sb.append(LS);
167             }
168         }
169 
170         return sb.toString();
171     }
172 
173     private static String constructMessageBase(
174             String message,
175             String groupId,
176             String artifactId,
177             String version,
178             String type,
179             List<ArtifactRepository> remoteRepositories,
180             List<String> path) {
181         StringBuilder sb = new StringBuilder();
182 
183         sb.append(message);
184 
185         if (message == null || !message.contains("from the specified remote repositories:")) {
186             sb.append(LS);
187             sb.append("  ")
188                     .append(groupId)
189                     .append(':')
190                     .append(artifactId)
191                     .append(':')
192                     .append(type)
193                     .append(':')
194                     .append(version);
195             sb.append(LS);
196             if (remoteRepositories != null) {
197                 sb.append(LS);
198                 sb.append("from the specified remote repositories:");
199                 sb.append(LS).append("  ");
200 
201                 if (remoteRepositories.isEmpty()) {
202                     sb.append("(none)");
203                 }
204 
205                 for (Iterator<ArtifactRepository> i = remoteRepositories.iterator(); i.hasNext(); ) {
206                     ArtifactRepository remoteRepository = i.next();
207 
208                     sb.append(remoteRepository.getId());
209                     sb.append(" (");
210                     sb.append(remoteRepository.getUrl());
211 
212                     ArtifactRepositoryPolicy releases = remoteRepository.getReleases();
213                     if (releases != null) {
214                         sb.append(", releases=").append(releases.isEnabled());
215                     }
216 
217                     ArtifactRepositoryPolicy snapshots = remoteRepository.getSnapshots();
218                     if (snapshots != null) {
219                         sb.append(", snapshots=").append(snapshots.isEnabled());
220                     }
221 
222                     sb.append(')');
223                     if (i.hasNext()) {
224                         sb.append(',').append(LS).append("  ");
225                     }
226                 }
227             }
228 
229             sb.append(constructArtifactPath(path, ""));
230             sb.append(LS);
231         }
232 
233         return sb.toString();
234     }
235 
236     @SuppressWarnings("checkstyle:parameternumber")
237     protected static String constructMissingArtifactMessage(
238             String message,
239             String indentation,
240             String groupId,
241             String artifactId,
242             String version,
243             String type,
244             String classifier,
245             String downloadUrl,
246             List<String> path) {
247         StringBuilder sb = new StringBuilder(message);
248 
249         if (!"pom".equals(type)) {
250             if (downloadUrl != null) {
251                 sb.append(LS);
252                 sb.append(LS);
253                 sb.append(indentation);
254                 sb.append("Try downloading the file manually from: ");
255                 sb.append(LS);
256                 sb.append(indentation);
257                 sb.append("    ");
258                 sb.append(downloadUrl);
259             } else {
260                 sb.append(LS);
261                 sb.append(LS);
262                 sb.append(indentation);
263                 sb.append("Try downloading the file manually from the project website.");
264             }
265 
266             sb.append(LS);
267             sb.append(LS);
268             sb.append(indentation);
269             sb.append("Then, install it using the command: ");
270             sb.append(LS);
271             sb.append(indentation);
272             sb.append("    mvn install:install-file -DgroupId=");
273             sb.append(groupId);
274             sb.append(" -DartifactId=");
275             sb.append(artifactId);
276             sb.append(" -Dversion=");
277             sb.append(version);
278 
279             // insert classifier only if it was used in the artifact
280             if (classifier != null && !classifier.equals("")) {
281                 sb.append(" -Dclassifier=");
282                 sb.append(classifier);
283             }
284             sb.append(" -Dpackaging=");
285             sb.append(type);
286             sb.append(" -Dfile=/path/to/file");
287             sb.append(LS);
288 
289             // If people want to deploy it
290             sb.append(LS);
291             sb.append(indentation);
292             sb.append("Alternatively, if you host your own repository you can deploy the file there: ");
293             sb.append(LS);
294             sb.append(indentation);
295             sb.append("    mvn deploy:deploy-file -DgroupId=");
296             sb.append(groupId);
297             sb.append(" -DartifactId=");
298             sb.append(artifactId);
299             sb.append(" -Dversion=");
300             sb.append(version);
301 
302             // insert classifier only if it was used in the artifact
303             if (classifier != null && !classifier.equals("")) {
304                 sb.append(" -Dclassifier=");
305                 sb.append(classifier);
306             }
307             sb.append(" -Dpackaging=");
308             sb.append(type);
309             sb.append(" -Dfile=/path/to/file");
310             sb.append(" -Durl=[url] -DrepositoryId=[id]");
311             sb.append(LS);
312         }
313 
314         sb.append(constructArtifactPath(path, indentation));
315         sb.append(LS);
316 
317         return sb.toString();
318     }
319 
320     public String getArtifactPath() {
321         return path;
322     }
323 }