001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.eclipse.aether;
020
021import java.io.Closeable;
022import java.util.Collection;
023import java.util.List;
024
025import org.eclipse.aether.artifact.Artifact;
026import org.eclipse.aether.collection.CollectRequest;
027import org.eclipse.aether.collection.CollectResult;
028import org.eclipse.aether.collection.DependencyCollectionException;
029import org.eclipse.aether.deployment.DeployRequest;
030import org.eclipse.aether.deployment.DeployResult;
031import org.eclipse.aether.deployment.DeploymentException;
032import org.eclipse.aether.graph.DependencyFilter;
033import org.eclipse.aether.graph.DependencyNode;
034import org.eclipse.aether.installation.InstallRequest;
035import org.eclipse.aether.installation.InstallResult;
036import org.eclipse.aether.installation.InstallationException;
037import org.eclipse.aether.metadata.Metadata;
038import org.eclipse.aether.repository.LocalRepository;
039import org.eclipse.aether.repository.LocalRepositoryManager;
040import org.eclipse.aether.repository.RemoteRepository;
041import org.eclipse.aether.resolution.ArtifactDescriptorException;
042import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
043import org.eclipse.aether.resolution.ArtifactDescriptorResult;
044import org.eclipse.aether.resolution.ArtifactRequest;
045import org.eclipse.aether.resolution.ArtifactResolutionException;
046import org.eclipse.aether.resolution.ArtifactResult;
047import org.eclipse.aether.resolution.DependencyRequest;
048import org.eclipse.aether.resolution.DependencyResolutionException;
049import org.eclipse.aether.resolution.DependencyResult;
050import org.eclipse.aether.resolution.MetadataRequest;
051import org.eclipse.aether.resolution.MetadataResult;
052import org.eclipse.aether.resolution.VersionRangeRequest;
053import org.eclipse.aether.resolution.VersionRangeResolutionException;
054import org.eclipse.aether.resolution.VersionRangeResult;
055import org.eclipse.aether.resolution.VersionRequest;
056import org.eclipse.aether.resolution.VersionResolutionException;
057import org.eclipse.aether.resolution.VersionResult;
058
059/**
060 * The main entry point to the repository system and its functionality. Note that obtaining a concrete implementation of
061 * this interface (e.g. via dependency injection, service locator, etc.) is dependent on the application and its
062 * specific needs, please consult the online documentation for examples and directions on booting the system.
063 * <p>
064 * When the repository system or the application integrating it is about to exit, invoke the {@link #shutdown()} to let
065 * resolver system perform possible resource cleanups.
066 *
067 * @noimplement This interface is not intended to be implemented by clients.
068 * @noextend This interface is not intended to be extended by clients.
069 */
070public interface RepositorySystem extends Closeable {
071
072    /**
073     * Expands an artifact's version range to a list of matching versions, in ascending order. For example, resolves "[3.8,4.0)" to
074     * "3.8", "3.8.1", "3.8.2". Note that the returned list of versions is only dependent on the configured repositories
075     * and their contents, the list is not processed by the {@link RepositorySystemSession#getVersionFilter() session's
076     * version filter}.
077     * <p>
078     * The supplied request may also refer to a single concrete version rather than a version range. In this case
079     * though, the result contains simply the (parsed) input version, regardless of the repositories and their contents.
080     *
081     * @param session The repository session, must not be {@code null}.
082     * @param request The version range request, must not be {@code null}. It holds the {@link Artifact} whose version range to resolve.
083     * @return The version range result, never {@code null}.
084     * @throws VersionRangeResolutionException If the requested range could not be parsed. Note that an empty range does
085     *                                         not raise an exception.
086     * @see #newResolutionRepositories(RepositorySystemSession, List)
087     * @see Artifact#getVersion()
088     */
089    VersionRangeResult resolveVersionRange(RepositorySystemSession session, VersionRangeRequest request)
090            throws VersionRangeResolutionException;
091
092    /**
093     * Resolves an artifact's meta version (if any) to a concrete version. For example, resolves "1.0-SNAPSHOT" to
094     * "1.0-20090208.132618-23".
095     *
096     * @param session The repository session, must not be {@code null}.
097     * @param request The version request, must not be {@code null}. It holds the {@link Artifact} whose version to resolve.
098     * @return The version result, never {@code null}.
099     * @throws VersionResolutionException If the metaversion could not be resolved.
100     * @see #newResolutionRepositories(RepositorySystemSession, List)
101     * @see Artifact#getVersion()
102     */
103    VersionResult resolveVersion(RepositorySystemSession session, VersionRequest request)
104            throws VersionResolutionException;
105
106    /**
107     * Gets information about an artifact like its direct dependencies and potential relocations.
108     *
109     * @param session The repository session, must not be {@code null}.
110     * @param request The descriptor request, must not be {@code null}.
111     * @return The descriptor result, never {@code null}.
112     * @throws ArtifactDescriptorException If the artifact descriptor could not be read.
113     * @see RepositorySystemSession#getArtifactDescriptorPolicy()
114     * @see #newResolutionRepositories(RepositorySystemSession, List)
115     */
116    ArtifactDescriptorResult readArtifactDescriptor(RepositorySystemSession session, ArtifactDescriptorRequest request)
117            throws ArtifactDescriptorException;
118
119    /**
120     * Collects the transitive dependencies of an artifact and builds a dependency graph. Note that this operation is
121     * only concerned about determining the coordinates of the transitive dependencies. To also resolve the actual
122     * artifact files, use {@link #resolveDependencies(RepositorySystemSession, DependencyRequest)}.
123     *
124     * @param session The repository session, must not be {@code null}.
125     * @param request The collection request, must not be {@code null}.
126     * @return The collection result, never {@code null}.
127     * @throws DependencyCollectionException If the dependency tree could not be built.
128     * @see RepositorySystemSession#getDependencyTraverser()
129     * @see RepositorySystemSession#getDependencyManager()
130     * @see RepositorySystemSession#getDependencySelector()
131     * @see RepositorySystemSession#getVersionFilter()
132     * @see RepositorySystemSession#getDependencyGraphTransformer()
133     * @see #newResolutionRepositories(RepositorySystemSession, List)
134     */
135    CollectResult collectDependencies(RepositorySystemSession session, CollectRequest request)
136            throws DependencyCollectionException;
137
138    /**
139     * Collects and resolves the transitive dependencies of an artifact. This operation is essentially a combination of
140     * {@link #collectDependencies(RepositorySystemSession, CollectRequest)} and
141     * {@link #resolveArtifacts(RepositorySystemSession, Collection)}.
142     *
143     * @param session The repository session, must not be {@code null}.
144     * @param request The dependency request, must not be {@code null}.
145     * @return The dependency result, never {@code null}.
146     * @throws DependencyResolutionException If the dependency tree could not be built or any dependency artifact could
147     *                                       not be resolved.
148     * @see #newResolutionRepositories(RepositorySystemSession, List)
149     */
150    DependencyResult resolveDependencies(RepositorySystemSession session, DependencyRequest request)
151            throws DependencyResolutionException;
152
153    /**
154     * Flattens the provided graph as {@link DependencyNode} into a {@link List}{@code <DependencyNode>} according to session
155     * configuration.
156     *
157     * @param session The repository session, must not be {@code null}.
158     * @param root The dependency node root of the graph, must not be {@code null}.
159     * @param filter The filter to apply, may be {@code null}.
160     * @return The flattened list of dependency nodes, never {@code null}.
161     * @since 2.0.0
162     */
163    List<DependencyNode> flattenDependencyNodes(
164            RepositorySystemSession session, DependencyNode root, DependencyFilter filter);
165
166    /**
167     * Resolves the path for an artifact. The artifact will be downloaded to the local repository if necessary. An
168     * artifact that is already resolved will be skipped and is not re-resolved. In general, callers must not assume any
169     * relationship between an artifact's resolved filename and its coordinates. Note that this method assumes that any
170     * relocations have already been processed.
171     *
172     * @param session The repository session, must not be {@code null}.
173     * @param request The resolution request, must not be {@code null}.
174     * @return The resolution result, never {@code null}.
175     * @throws ArtifactResolutionException If the artifact could not be resolved.
176     * @see Artifact#getFile()
177     * @see #newResolutionRepositories(RepositorySystemSession, List)
178     */
179    ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request)
180            throws ArtifactResolutionException;
181
182    /**
183     * Resolves the paths for a collection of artifacts. Artifacts will be downloaded to the local repository if
184     * necessary. Artifacts that are already resolved will be skipped and are not re-resolved. In general, callers must
185     * not assume any relationship between an artifact's filename and its coordinates. Note that this method assumes
186     * that any relocations have already been processed.
187     *
188     * @param session  The repository session, must not be {@code null}.
189     * @param requests The resolution requests, must not be {@code null}.
190     * @return The resolution results (in request order), never {@code null}.
191     * @throws ArtifactResolutionException If any artifact could not be resolved.
192     * @see Artifact#getFile()
193     * @see #newResolutionRepositories(RepositorySystemSession, List)
194     */
195    List<ArtifactResult> resolveArtifacts(
196            RepositorySystemSession session, Collection<? extends ArtifactRequest> requests)
197            throws ArtifactResolutionException;
198
199    /**
200     * Resolves the paths for a collection of metadata. Metadata will be downloaded to the local repository if
201     * necessary, e.g. because it hasn't been cached yet or the cache is deemed outdated.
202     *
203     * @param session  The repository session, must not be {@code null}.
204     * @param requests The resolution requests, must not be {@code null}.
205     * @return The resolution results (in request order), never {@code null}.
206     * @see Metadata#getFile()
207     * @see #newResolutionRepositories(RepositorySystemSession, List)
208     */
209    List<MetadataResult> resolveMetadata(
210            RepositorySystemSession session, Collection<? extends MetadataRequest> requests);
211
212    /**
213     * Installs a collection of artifacts and their accompanying metadata to the local repository.
214     *
215     * @param session The repository session, must not be {@code null}.
216     * @param request The installation request, must not be {@code null}.
217     * @return The installation result, never {@code null}.
218     * @throws InstallationException If any artifact/metadata from the request could not be installed.
219     */
220    InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException;
221
222    /**
223     * Uploads a collection of artifacts and their accompanying metadata to a remote repository.
224     *
225     * @param session The repository session, must not be {@code null}.
226     * @param request The deployment request, must not be {@code null}.
227     * @return The deployment result, never {@code null}.
228     * @throws DeploymentException If any artifact/metadata from the request could not be deployed.
229     * @see #newDeploymentRepository(RepositorySystemSession, RemoteRepository)
230     */
231    DeployResult deploy(RepositorySystemSession session, DeployRequest request) throws DeploymentException;
232
233    /**
234     * Creates a new manager for the specified local repository. If the specified local repository has no type, the
235     * default local repository type of the system will be used. <em>Note:</em> It is expected that this method
236     * invocation is one of the last steps of setting up a new session, in particular any configuration properties
237     * should have been set already.
238     *
239     * @param session         The repository system session from which to configure the manager, must not be
240     *                        {@code null}.
241     * @param localRepository The local repository to create a manager for, must not be {@code null}.
242     * @return The local repository manager, never {@code null}.
243     * @throws IllegalArgumentException If the specified repository type is not recognized or no base directory is
244     *                                  given.
245     */
246    LocalRepositoryManager newLocalRepositoryManager(RepositorySystemSession session, LocalRepository localRepository);
247
248    /**
249     * Creates a new manager for the specified local repositories. If the specified local repository has no type, the
250     * default local repository type of the system will be used. <em>Note:</em> It is expected that this method
251     * invocation is one of the last steps of setting up a new session, in particular any configuration properties
252     * should have been set already. <em>Note:</em> this method accepts multiple local repositories, in which case
253     * it creates chained local repository.
254     *
255     * @param session         The repository system session from which to configure the manager, must not be
256     *                        {@code null}.
257     * @param localRepositories The local repositories to create a manager for, must not be {@code null} nor empty array.
258     * @return The local repository manager, never {@code null}.
259     * @throws IllegalArgumentException If the specified repository type is not recognized or no base directory is
260     *                                  given.
261     * @since 2.0.0
262     */
263    LocalRepositoryManager newLocalRepositoryManager(
264            RepositorySystemSession session, LocalRepository... localRepositories);
265
266    /**
267     * Creates a new manager for the specified local repositories. If the specified local repository has no type, the
268     * default local repository type of the system will be used. <em>Note:</em> It is expected that this method
269     * invocation is one of the last steps of setting up a new session, in particular any configuration properties
270     * should have been set already. <em>Note:</em> this method accepts multiple local repositories, in which case
271     * it creates chained local repository.
272     *
273     * @param session         The repository system session from which to configure the manager, must not be
274     *                        {@code null}.
275     * @param localRepositories The local repositories to create a manager for, must not be {@code null} nor empty.
276     * @return The local repository manager, never {@code null}.
277     * @throws IllegalArgumentException If the specified repository type is not recognized or no base directory is
278     *                                  given.
279     * @since 2.0.0
280     */
281    LocalRepositoryManager newLocalRepositoryManager(
282            RepositorySystemSession session, List<LocalRepository> localRepositories);
283
284    /**
285     * Creates a new synchronization context.
286     *
287     * @param session The repository session during which the context will be used, must not be {@code null}.
288     * @param shared  A flag indicating whether access to the artifacts/metadata associated with the new context can be
289     *                shared among concurrent readers or whether access needs to be exclusive to the calling thread.
290     * @return The synchronization context, never {@code null}.
291     */
292    SyncContext newSyncContext(RepositorySystemSession session, boolean shared);
293
294    /**
295     * Forms remote repositories suitable for artifact resolution by applying the session's authentication selector and
296     * similar network configuration to the given repository prototypes. As noted for
297     * {@link RepositorySystemSession#getAuthenticationSelector()} etc. the remote repositories passed to e.g.
298     * {@link #resolveArtifact(RepositorySystemSession, ArtifactRequest) resolveArtifact()} are used as is and expected
299     * to already carry any required authentication or proxy configuration. This method can be used to apply the
300     * authentication/proxy configuration from a session to a bare repository definition to obtain the complete
301     * repository definition for use in the resolution request.
302     *
303     * @param session      The repository system session from which to configure the repositories, must not be
304     *                     {@code null}.
305     * @param repositories The repository prototypes from which to derive the resolution repositories, must not be
306     *                     {@code null} or contain {@code null} elements.
307     * @return The resolution repositories, never {@code null}. Note that there is generally no 1:1 relationship of the
308     * obtained repositories to the original inputs due to mirror selection potentially aggregating multiple
309     * repositories.
310     * @see #newDeploymentRepository(RepositorySystemSession, RemoteRepository)
311     */
312    List<RemoteRepository> newResolutionRepositories(
313            RepositorySystemSession session, List<RemoteRepository> repositories);
314
315    /**
316     * Forms a remote repository suitable for artifact deployment by applying the session's authentication selector and
317     * similar network configuration to the given repository prototype. As noted for
318     * {@link RepositorySystemSession#getAuthenticationSelector()} etc. the remote repository passed to
319     * {@link #deploy(RepositorySystemSession, DeployRequest) deploy()} is used as is and expected to already carry any
320     * required authentication or proxy configuration. This method can be used to apply the authentication/proxy
321     * configuration from a session to a bare repository definition to obtain the complete repository definition for use
322     * in the deployment request.
323     *
324     * @param session    The repository system session from which to configure the repository, must not be {@code null}.
325     * @param repository The repository prototype from which to derive the deployment repository, must not be
326     *                   {@code null}.
327     * @return The deployment repository, never {@code null}.
328     * @see #newResolutionRepositories(RepositorySystemSession, List)
329     */
330    RemoteRepository newDeploymentRepository(RepositorySystemSession session, RemoteRepository repository);
331
332    /**
333     * Registers an "on repository system end" handler, executed after repository system is shut down.
334     *
335     * @param handler The handler, must not be {@code null}.
336     * @since 1.9.0
337     */
338    void addOnSystemEndedHandler(Runnable handler);
339
340    /**
341     * Creates a brand-new session builder instance that produces "top level" (root) session. Top level sessions are
342     * associated with its creator {@link RepositorySystem} instance, and may be used only with that given instance and
343     * only within the lifespan of it, and after use should be closed.
344     *
345     * @since 2.0.0
346     */
347    RepositorySystemSession.SessionBuilder createSessionBuilder();
348
349    /**
350     * Signals to repository system to shut down. Shut down instance is not usable anymore.
351     * <p>
352     * Repository system may perform some resource cleanup, if applicable. Not using this method may cause leaks or
353     * unclean shutdown of some subsystem.
354     * <p>
355     * When shutdown happens, all the registered on-close handlers will be invoked (even if some throws), and at end
356     * of operation a {@link MultiRuntimeException} may be thrown, signaling that some handler(s) failed. This exception
357     * may be ignored, is at the discretion of caller.
358     *
359     * @since 1.9.0
360     */
361    void shutdown();
362
363    /**
364     * Closes this instance, invokes {@link #shutdown()}.
365     *
366     * @since 2.0.0
367     */
368    @Override
369    default void close() {
370        shutdown();
371    }
372}