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