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.api.services;
20  
21  import java.util.HashSet;
22  import java.util.List;
23  import java.util.Objects;
24  
25  import org.apache.maven.api.RemoteRepository;
26  import org.apache.maven.api.Session;
27  import org.apache.maven.api.annotations.Experimental;
28  import org.apache.maven.api.annotations.Immutable;
29  import org.apache.maven.api.annotations.Nullable;
30  
31  /**
32   * Base interface for service requests that involve remote repository operations.
33   * This interface provides common functionality for requests that need to specify
34   * and validate remote repositories for artifact resolution, dependency collection,
35   * model building, and other Maven operations.
36   *
37   * <p>Implementations of this interface can specify a list of remote repositories
38   * to be used during the operation. If no repositories are specified (null),
39   * the session's default remote repositories will be used. The repositories
40   * are validated to ensure they don't contain duplicates or null entries.
41   *
42   * <p>Remote repositories are used for:
43   * <ul>
44   *   <li>Resolving artifacts and their metadata</li>
45   *   <li>Downloading parent POMs and dependency POMs</li>
46   *   <li>Retrieving version information and ranges</li>
47   *   <li>Accessing plugin artifacts and their dependencies</li>
48   * </ul>
49   *
50   * <p>Repository validation ensures data integrity by:
51   * <ul>
52   *   <li>Preventing duplicate repositories that could cause confusion</li>
53   *   <li>Rejecting null repository entries that would cause failures</li>
54   *   <li>Maintaining consistent repository ordering for reproducible builds</li>
55   * </ul>
56   *
57   * @since 4.0.0
58   * @see RemoteRepository
59   * @see Session#getRemoteRepositories()
60   */
61  @Experimental
62  @Immutable
63  public interface RepositoryAwareRequest extends Request<Session> {
64  
65      /**
66       * Returns the list of remote repositories to be used for this request.
67       *
68       * <p>If this method returns {@code null}, the session's default remote repositories
69       * will be used. If a non-null list is returned, it will be used instead of the
70       * session's repositories, allowing for request-specific repository configuration.
71       *
72       * <p>The returned list should not contain duplicate repositories (based on their
73       * equality) or null entries, as these will cause validation failures when the
74       * request is processed.
75       *
76       * @return the list of remote repositories to use, or {@code null} to use session defaults
77       * @see Session#getRemoteRepositories()
78       */
79      @Nullable
80      List<RemoteRepository> getRepositories();
81  
82      /**
83       * Validates a list of remote repositories to ensure data integrity.
84       *
85       * <p>This method performs the following validations:
86       * <ul>
87       *   <li>Allows null input (returns null)</li>
88       *   <li>Ensures no duplicate repositories exist in the list</li>
89       *   <li>Ensures no null repository entries exist in the list</li>
90       * </ul>
91       *
92       * <p>Duplicate detection is based on the {@code RemoteRepository#equals(Object)}
93       * method, which typically compares repository IDs and URLs.
94       *
95       * @param repositories the list of repositories to validate, may be {@code null}
96       * @return the same list if validation passes, or {@code null} if input was {@code null}
97       * @throws IllegalArgumentException if the list contains duplicate repositories
98       * @throws IllegalArgumentException if the list contains null repository entries
99       */
100     default List<RemoteRepository> validate(List<RemoteRepository> repositories) {
101         if (repositories == null) {
102             return null;
103         }
104         HashSet<RemoteRepository> set = new HashSet<>(repositories);
105         if (repositories.size() != set.size()) {
106             throw new IllegalArgumentException(
107                     "Repository list contains duplicate entries. Each repository must be unique based on its ID and URL. "
108                             + "Found " + repositories.size() + " repositories but only " + set.size()
109                             + " unique entries.");
110         }
111         if (repositories.stream().anyMatch(Objects::isNull)) {
112             throw new IllegalArgumentException(
113                     "Repository list contains null entries. All repository entries must be non-null RemoteRepository instances.");
114         }
115         return repositories;
116     }
117 }