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