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.ArrayList;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.concurrent.ConcurrentHashMap;
25  import java.util.concurrent.CopyOnWriteArrayList;
26  
27  import org.eclipse.aether.RepositorySystem;
28  import org.eclipse.aether.artifact.Artifact;
29  import org.eclipse.aether.repository.ArtifactRepository;
30  import org.eclipse.aether.repository.LocalArtifactResult;
31  import org.eclipse.aether.transfer.ArtifactNotFoundException;
32  
33  import static java.util.Objects.requireNonNull;
34  
35  /**
36   * The result of an artifact resolution request.
37   *
38   * @see RepositorySystem#resolveArtifacts(org.eclipse.aether.RepositorySystemSession, java.util.Collection)
39   * @see Artifact#getPath()
40   */
41  public final class ArtifactResult {
42  
43      /**
44       * A sentinel object, that is used as key for exceptions that had no related repository during resolution.
45       *
46       * @since 2.0.0
47       */
48      public static final ArtifactRepository NO_REPOSITORY = new NoRepository();
49  
50      private static final class NoRepository implements ArtifactRepository {
51  
52          private NoRepository() {}
53  
54          public String getContentType() {
55              return "unknown";
56          }
57  
58          public String getId() {
59              return "unknown";
60          }
61  
62          @Override
63          public String toString() {
64              return getId();
65          }
66      }
67  
68      private final ArtifactRequest request;
69  
70      private final Map<ArtifactRepository, List<Exception>> exceptions;
71  
72      private Artifact artifact;
73  
74      private ArtifactRepository repository;
75  
76      private LocalArtifactResult localArtifactResult;
77  
78      /**
79       * Creates a new result for the specified request.
80       *
81       * @param request The resolution request, must not be {@code null}.
82       */
83      public ArtifactResult(ArtifactRequest request) {
84          this.request = requireNonNull(request, "artifact request cannot be null");
85          this.exceptions = new ConcurrentHashMap<>();
86      }
87  
88      /**
89       * Gets the resolution request that was made.
90       *
91       * @return The resolution request, never {@code null}.
92       */
93      public ArtifactRequest getRequest() {
94          return request;
95      }
96  
97      /**
98       * Gets the resolved artifact (if any). Use {@link #getExceptions()} to query the errors that occurred while trying
99       * to resolve the artifact.
100      *
101      * @return The resolved artifact or {@code null} if the resolution failed.
102      */
103     public Artifact getArtifact() {
104         return artifact;
105     }
106 
107     /**
108      * Sets the resolved artifact.
109      *
110      * @param artifact The resolved artifact, may be {@code null} if the resolution failed.
111      * @return This result for chaining, never {@code null}.
112      */
113     public ArtifactResult setArtifact(Artifact artifact) {
114         this.artifact = artifact;
115         return this;
116     }
117 
118     /**
119      * Gets the exceptions that occurred while resolving the artifact. Note that this list can be non-empty even if the
120      * artifact was successfully resolved, e.g. when one of the contacted remote repositories didn't contain the
121      * artifact but a later repository eventually contained it.
122      *
123      * @return The exceptions that occurred, never {@code null}.
124      * @see #isResolved()
125      * @see #isMissing()
126      */
127     public List<Exception> getExceptions() {
128         ArrayList<Exception> result = new ArrayList<>();
129         exceptions.values().forEach(result::addAll);
130         return result;
131     }
132 
133     /**
134      * Gets the exceptions that occurred while resolving the artifact. Note that this map can be non-empty even if the
135      * artifact was successfully resolved, e.g. when one of the contacted remote repositories didn't contain the
136      * artifact but a later repository eventually contained it.
137      *
138      * @return Map of exceptions per repository, that occurred during resolution, never {@code null}.
139      * @see #isResolved()
140      * @see #isMissing()
141      * @since 2.0.0
142      */
143     public Map<ArtifactRepository, List<Exception>> getMappedExceptions() {
144         return exceptions;
145     }
146 
147     /**
148      * Records the specified exception while resolving the artifact.
149      *
150      * @param exception The exception to record, may be {@code null}.
151      * @return This result for chaining, never {@code null}.
152      * @deprecated Use {@link #addException(ArtifactRepository, Exception)} method instead.
153      */
154     @Deprecated
155     public ArtifactResult addException(Exception exception) {
156         return addException(NO_REPOSITORY, exception);
157     }
158 
159     /**
160      * Records the specified exception while resolving the artifact.
161      *
162      * @param exception The exception to record, may be {@code null}.
163      * @return This result for chaining, never {@code null}.
164      * @since 2.0.0
165      */
166     public ArtifactResult addException(ArtifactRepository repository, Exception exception) {
167         if (repository != null && exception != null) {
168             exceptions
169                     .computeIfAbsent(repository, k -> new CopyOnWriteArrayList<>())
170                     .add(exception);
171         }
172         return this;
173     }
174 
175     /**
176      * Gets the repository from which the artifact was eventually resolved. Note that successive resolutions of the same
177      * artifact might yield different results if the employed local repository does not track the origin of an artifact.
178      *
179      * @return The repository from which the artifact was resolved or {@code null} if unknown.
180      */
181     public ArtifactRepository getRepository() {
182         return repository;
183     }
184 
185     /**
186      * Sets the repository from which the artifact was resolved.
187      *
188      * @param repository The repository from which the artifact was resolved, may be {@code null}.
189      * @return This result for chaining, never {@code null}.
190      */
191     public ArtifactResult setRepository(ArtifactRepository repository) {
192         this.repository = repository;
193         return this;
194     }
195 
196     /**
197      * Gets the {@link LocalArtifactResult} received during artifact resolution.
198      *
199      * @return The {@link LocalArtifactResult} or {@code null}.
200      * @since 1.9.6
201      */
202     public LocalArtifactResult getLocalArtifactResult() {
203         return localArtifactResult;
204     }
205 
206     /**
207      * Sets the {@link LocalArtifactResult} that is received during artifact resolution.
208      *
209      * @param localArtifactResult The local artifact result.
210      * @since 1.9.6
211      */
212     public void setLocalArtifactResult(LocalArtifactResult localArtifactResult) {
213         this.localArtifactResult = localArtifactResult;
214     }
215 
216     /**
217      * Indicates whether the requested artifact was resolved. Note that the artifact might have been successfully
218      * resolved despite {@link #getExceptions()} indicating transfer errors while trying to fetch the artifact from some
219      * of the specified remote repositories.
220      *
221      * @return {@code true} if the artifact was resolved, {@code false} otherwise.
222      * @see Artifact#getPath()
223      */
224     public boolean isResolved() {
225         return getArtifact() != null && getArtifact().getPath() != null;
226     }
227 
228     /**
229      * Indicates whether the requested artifact is not present in any of the specified repositories.
230      *
231      * @return {@code true} if the artifact is not present in any repository, {@code false} otherwise.
232      */
233     public boolean isMissing() {
234         for (Exception e : getExceptions()) {
235             if (!(e instanceof ArtifactNotFoundException)) {
236                 return false;
237             }
238         }
239         return !isResolved();
240     }
241 
242     @Override
243     public String toString() {
244         return getArtifact() + " < " + getRepository();
245     }
246 }