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.internal.impl; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.util.ArrayList; 026import java.util.List; 027import java.util.ListIterator; 028import java.util.stream.Collectors; 029 030import org.eclipse.aether.Keys; 031import org.eclipse.aether.RepositoryCache; 032import org.eclipse.aether.RepositorySystemSession; 033import org.eclipse.aether.impl.RemoteRepositoryManager; 034import org.eclipse.aether.impl.UpdatePolicyAnalyzer; 035import org.eclipse.aether.repository.Authentication; 036import org.eclipse.aether.repository.AuthenticationSelector; 037import org.eclipse.aether.repository.MirrorSelector; 038import org.eclipse.aether.repository.Proxy; 039import org.eclipse.aether.repository.ProxySelector; 040import org.eclipse.aether.repository.RemoteRepository; 041import org.eclipse.aether.repository.RepositoryKeyFunction; 042import org.eclipse.aether.repository.RepositoryPolicy; 043import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider; 044import org.eclipse.aether.spi.remoterepo.RepositoryKeyFunctionFactory; 045import org.slf4j.Logger; 046import org.slf4j.LoggerFactory; 047 048import static java.util.Objects.requireNonNull; 049 050/** 051 */ 052@Singleton 053@Named 054public class DefaultRemoteRepositoryManager implements RemoteRepositoryManager { 055 056 private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRemoteRepositoryManager.class); 057 058 private final UpdatePolicyAnalyzer updatePolicyAnalyzer; 059 060 private final ChecksumPolicyProvider checksumPolicyProvider; 061 062 private final RepositoryKeyFunctionFactory repositoryKeyFunctionFactory; 063 064 @Inject 065 public DefaultRemoteRepositoryManager( 066 UpdatePolicyAnalyzer updatePolicyAnalyzer, 067 ChecksumPolicyProvider checksumPolicyProvider, 068 RepositoryKeyFunctionFactory repositoryKeyFunctionFactory) { 069 this.updatePolicyAnalyzer = requireNonNull(updatePolicyAnalyzer, "update policy analyzer cannot be null"); 070 this.checksumPolicyProvider = requireNonNull(checksumPolicyProvider, "checksum policy provider cannot be null"); 071 this.repositoryKeyFunctionFactory = 072 requireNonNull(repositoryKeyFunctionFactory, "repository key function factory cannot be null"); 073 } 074 075 @Override 076 public List<RemoteRepository> aggregateRepositories( 077 RepositorySystemSession session, 078 List<RemoteRepository> dominantRepositories, 079 List<RemoteRepository> recessiveRepositories, 080 boolean recessiveIsRaw) { 081 requireNonNull(session, "session cannot be null"); 082 requireNonNull(dominantRepositories, "dominantRepositories cannot be null"); 083 requireNonNull(recessiveRepositories, "recessiveRepositories cannot be null"); 084 if (recessiveRepositories.isEmpty()) { 085 return dominantRepositories; 086 } 087 088 RepositoryKeyFunction repositoryKeyFunction = repositoryKeyFunctionFactory.systemRepositoryKeyFunction(session); 089 MirrorSelector mirrorSelector = session.getMirrorSelector(); 090 AuthenticationSelector authSelector = session.getAuthenticationSelector(); 091 ProxySelector proxySelector = session.getProxySelector(); 092 093 List<RemoteRepository> result = new ArrayList<>(dominantRepositories); 094 095 next: 096 for (RemoteRepository recessiveRepository : recessiveRepositories) { 097 RemoteRepository repository = recessiveRepository; 098 099 if (recessiveIsRaw) { 100 RemoteRepository mirrorRepository = mirrorSelector.getMirror(recessiveRepository); 101 102 if (mirrorRepository != null) { 103 logMirror(session, recessiveRepository, mirrorRepository); 104 repository = mirrorRepository; 105 } 106 } 107 108 String key = repositoryKeyFunction.apply(repository, null); 109 110 for (ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); ) { 111 RemoteRepository dominantRepository = it.next(); 112 113 if (key.equals(repositoryKeyFunction.apply(dominantRepository, null))) { 114 if (!dominantRepository.getMirroredRepositories().isEmpty() 115 && !repository.getMirroredRepositories().isEmpty()) { 116 RemoteRepository mergedRepository = 117 mergeMirrors(session, repositoryKeyFunction, dominantRepository, repository); 118 if (mergedRepository != dominantRepository) { 119 it.set(mergedRepository); 120 } 121 } 122 123 continue next; 124 } 125 } 126 127 if (recessiveIsRaw) { 128 RemoteRepository.Builder builder = null; 129 Authentication auth = authSelector.getAuthentication(repository); 130 if (auth != null) { 131 builder = new RemoteRepository.Builder(repository); 132 builder.setAuthentication(auth); 133 } 134 Proxy proxy = proxySelector.getProxy(repository); 135 if (proxy != null) { 136 if (builder == null) { 137 builder = new RemoteRepository.Builder(repository); 138 } 139 builder.setProxy(proxy); 140 } 141 if (builder != null) { 142 repository = builder.build(); 143 } 144 } 145 146 result.add(repository); 147 } 148 149 return result.stream() 150 .map(r -> new RemoteRepository.Builder(r) 151 .setIntent(RemoteRepository.Intent.RESOLUTION) 152 .build()) 153 .collect(Collectors.toList()); 154 } 155 156 private void logMirror(RepositorySystemSession session, RemoteRepository original, RemoteRepository mirror) { 157 if (!LOGGER.isDebugEnabled()) { 158 return; 159 } 160 RepositoryCache cache = session.getCache(); 161 if (cache != null) { 162 Object key = Keys.of(mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl()); 163 if (cache.get(session, key) != null) { 164 return; 165 } 166 cache.put(session, key, Boolean.TRUE); 167 } 168 LOGGER.debug( 169 "Using mirror {} ({}) for {} ({}).", 170 mirror.getId(), 171 mirror.getUrl(), 172 original.getId(), 173 original.getUrl()); 174 } 175 176 private RemoteRepository mergeMirrors( 177 RepositorySystemSession session, 178 RepositoryKeyFunction repositoryKeyFunction, 179 RemoteRepository dominant, 180 RemoteRepository recessive) { 181 RemoteRepository.Builder merged = null; 182 RepositoryPolicy releases = null, snapshots = null; 183 184 next: 185 for (RemoteRepository rec : recessive.getMirroredRepositories()) { 186 String recKey = repositoryKeyFunction.apply(rec, null); 187 188 for (RemoteRepository dom : dominant.getMirroredRepositories()) { 189 if (recKey.equals(repositoryKeyFunction.apply(dom, null))) { 190 continue next; 191 } 192 } 193 194 if (merged == null) { 195 merged = new RemoteRepository.Builder(dominant); 196 releases = dominant.getPolicy(false); 197 snapshots = dominant.getPolicy(true); 198 } 199 200 releases = merge(session, releases, rec.getPolicy(false), false); 201 snapshots = merge(session, snapshots, rec.getPolicy(true), false); 202 203 merged.addMirroredRepository(rec); 204 } 205 206 if (merged == null) { 207 return dominant; 208 } 209 return merged.setReleasePolicy(releases).setSnapshotPolicy(snapshots).build(); 210 } 211 212 @Override 213 public RepositoryPolicy getPolicy( 214 RepositorySystemSession session, RemoteRepository repository, boolean releases, boolean snapshots) { 215 requireNonNull(session, "session cannot be null"); 216 requireNonNull(repository, "repository cannot be null"); 217 RepositoryPolicy policy1 = releases ? repository.getPolicy(false) : null; 218 RepositoryPolicy policy2 = snapshots ? repository.getPolicy(true) : null; 219 return merge(session, policy1, policy2, true); 220 } 221 222 private RepositoryPolicy merge( 223 RepositorySystemSession session, RepositoryPolicy policy1, RepositoryPolicy policy2, boolean globalPolicy) { 224 RepositoryPolicy policy; 225 226 if (policy2 == null) { 227 if (globalPolicy) { 228 policy = merge( 229 policy1, 230 session.getArtifactUpdatePolicy(), 231 session.getMetadataUpdatePolicy(), 232 session.getChecksumPolicy()); 233 } else { 234 policy = policy1; 235 } 236 } else if (policy1 == null) { 237 if (globalPolicy) { 238 policy = merge( 239 policy2, 240 session.getArtifactUpdatePolicy(), 241 session.getMetadataUpdatePolicy(), 242 session.getChecksumPolicy()); 243 } else { 244 policy = policy2; 245 } 246 } else if (!policy2.isEnabled()) { 247 if (globalPolicy) { 248 policy = merge( 249 policy1, 250 session.getArtifactUpdatePolicy(), 251 session.getMetadataUpdatePolicy(), 252 session.getChecksumPolicy()); 253 } else { 254 policy = policy1; 255 } 256 } else if (!policy1.isEnabled()) { 257 if (globalPolicy) { 258 policy = merge( 259 policy2, 260 session.getArtifactUpdatePolicy(), 261 session.getMetadataUpdatePolicy(), 262 session.getChecksumPolicy()); 263 } else { 264 policy = policy2; 265 } 266 } else { 267 String checksums = session.getChecksumPolicy(); 268 //noinspection StatementWithEmptyBody 269 if (globalPolicy && checksums != null && !checksums.isEmpty()) { 270 // use global override 271 } else { 272 checksums = checksumPolicyProvider.getEffectiveChecksumPolicy( 273 session, policy1.getChecksumPolicy(), policy2.getChecksumPolicy()); 274 } 275 276 String artifactUpdates = session.getArtifactUpdatePolicy(); 277 //noinspection StatementWithEmptyBody 278 if (globalPolicy && artifactUpdates != null && !artifactUpdates.isEmpty()) { 279 // use global override 280 } else { 281 artifactUpdates = updatePolicyAnalyzer.getEffectiveUpdatePolicy( 282 session, policy1.getArtifactUpdatePolicy(), policy2.getArtifactUpdatePolicy()); 283 } 284 String metadataUpdates = session.getMetadataUpdatePolicy(); 285 if (globalPolicy && metadataUpdates != null && !metadataUpdates.isEmpty()) { 286 // use global override 287 } else { 288 metadataUpdates = updatePolicyAnalyzer.getEffectiveUpdatePolicy( 289 session, policy1.getMetadataUpdatePolicy(), policy2.getMetadataUpdatePolicy()); 290 } 291 292 policy = new RepositoryPolicy(true, artifactUpdates, metadataUpdates, checksums); 293 } 294 295 return policy; 296 } 297 298 private RepositoryPolicy merge( 299 RepositoryPolicy policy, String artifactUpdates, String metadataUpdates, String checksums) { 300 if (policy != null) { 301 if (artifactUpdates == null || artifactUpdates.isEmpty()) { 302 artifactUpdates = policy.getArtifactUpdatePolicy(); 303 } 304 if (metadataUpdates == null || metadataUpdates.isEmpty()) { 305 metadataUpdates = policy.getMetadataUpdatePolicy(); 306 } 307 if (checksums == null || checksums.isEmpty()) { 308 checksums = policy.getChecksumPolicy(); 309 } 310 if (!policy.getArtifactUpdatePolicy().equals(artifactUpdates) 311 || !policy.getMetadataUpdatePolicy().equals(metadataUpdates) 312 || !policy.getChecksumPolicy().equals(checksums)) { 313 policy = new RepositoryPolicy(policy.isEnabled(), artifactUpdates, metadataUpdates, checksums); 314 } 315 } 316 return policy; 317 } 318}