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.resolution;
20  
21  import java.util.Collections;
22  import java.util.List;
23  
24  import org.eclipse.aether.RepositoryException;
25  import org.eclipse.aether.repository.LocalArtifactResult;
26  import org.eclipse.aether.transfer.ArtifactFilteredOutException;
27  import org.eclipse.aether.transfer.ArtifactNotFoundException;
28  import org.eclipse.aether.transfer.RepositoryOfflineException;
29  
30  /**
31   * Thrown in case of a unresolvable artifacts.
32   */
33  public class ArtifactResolutionException extends RepositoryException {
34  
35      private final transient List<ArtifactResult> results;
36  
37      /**
38       * Creates a new exception with the specified results.
39       *
40       * @param results The resolution results at the point the exception occurred, may be {@code null}.
41       */
42      public ArtifactResolutionException(List<ArtifactResult> results) {
43          super(getMessage(results), getCause(results));
44          this.results = (results != null) ? results : Collections.<ArtifactResult>emptyList();
45      }
46  
47      /**
48       * Creates a new exception with the specified results and detail message.
49       *
50       * @param results The resolution results at the point the exception occurred, may be {@code null}.
51       * @param message The detail message, may be {@code null}.
52       */
53      public ArtifactResolutionException(List<ArtifactResult> results, String message) {
54          super(message, getCause(results));
55          this.results = (results != null) ? results : Collections.<ArtifactResult>emptyList();
56      }
57  
58      /**
59       * Creates a new exception with the specified results, detail message and cause.
60       *
61       * @param results The resolution results at the point the exception occurred, may be {@code null}.
62       * @param message The detail message, may be {@code null}.
63       * @param cause The exception that caused this one, may be {@code null}.
64       */
65      public ArtifactResolutionException(List<ArtifactResult> results, String message, Throwable cause) {
66          super(message, cause);
67          this.results = (results != null) ? results : Collections.<ArtifactResult>emptyList();
68      }
69  
70      /**
71       * Gets the resolution results at the point the exception occurred. Despite being incomplete, callers might want to
72       * use these results to fail gracefully and continue their operation with whatever interim data has been gathered.
73       *
74       * @return The resolution results or {@code null} if unknown.
75       */
76      public List<ArtifactResult> getResults() {
77          return results;
78      }
79  
80      /**
81       * Gets the first result from {@link #getResults()}. This is a convenience method for cases where callers know only
82       * a single result/request is involved.
83       *
84       * @return The (first) resolution result or {@code null} if none.
85       */
86      public ArtifactResult getResult() {
87          return (results != null && !results.isEmpty()) ? results.get(0) : null;
88      }
89  
90      private static String getMessage(List<? extends ArtifactResult> results) {
91          StringBuilder buffer = new StringBuilder(256);
92  
93          buffer.append("The following artifacts could not be resolved: ");
94  
95          String sep = "";
96          for (ArtifactResult result : results) {
97              if (!result.isResolved()) {
98                  buffer.append(sep);
99                  buffer.append(result.getRequest().getArtifact());
100                 LocalArtifactResult localResult = result.getLocalArtifactResult();
101                 if (localResult != null) {
102                     buffer.append(" (");
103                     if (localResult.getFile() != null) {
104                         buffer.append("present");
105                         if (!localResult.isAvailable()) {
106                             buffer.append(", but unavailable");
107                         }
108                     } else {
109                         buffer.append("absent");
110                     }
111                     buffer.append(")");
112                 }
113                 sep = ", ";
114             }
115         }
116 
117         Throwable cause = getCause(results);
118         if (cause != null) {
119             buffer.append(": ").append(cause.getMessage());
120         }
121 
122         return buffer.toString();
123     }
124 
125     private static Throwable getCause(List<? extends ArtifactResult> results) {
126         for (ArtifactResult result : results) {
127             if (!result.isResolved()) {
128                 Throwable notFound = null, offline = null;
129                 for (Throwable t : result.getExceptions()) {
130                     if (t instanceof ArtifactNotFoundException) {
131                         if (notFound == null || notFound instanceof ArtifactFilteredOutException) {
132                             notFound = t;
133                         }
134                         if (offline == null && t.getCause() instanceof RepositoryOfflineException) {
135                             offline = t;
136                         }
137                     } else {
138                         return t;
139                     }
140                 }
141                 if (offline != null) {
142                     return offline;
143                 }
144                 if (notFound != null) {
145                     return notFound;
146                 }
147             }
148         }
149         return null;
150     }
151 }