001package org.eclipse.aether.internal.impl; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.List; 025import java.util.ListIterator; 026import static java.util.Objects.requireNonNull; 027 028import javax.inject.Inject; 029import javax.inject.Named; 030 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.RepositoryPolicy; 042import org.eclipse.aether.spi.connector.checksum.ChecksumPolicyProvider; 043import org.eclipse.aether.spi.locator.Service; 044import org.eclipse.aether.spi.locator.ServiceLocator; 045import org.eclipse.aether.util.StringUtils; 046import org.slf4j.Logger; 047import org.slf4j.LoggerFactory; 048 049/** 050 */ 051@Named 052public class DefaultRemoteRepositoryManager 053 implements RemoteRepositoryManager, Service 054{ 055 056 private static final class LoggedMirror 057 { 058 059 private final Object[] keys; 060 061 LoggedMirror( RemoteRepository original, RemoteRepository mirror ) 062 { 063 keys = new Object[] { mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl() }; 064 } 065 066 @Override 067 public boolean equals( Object obj ) 068 { 069 if ( this == obj ) 070 { 071 return true; 072 } 073 else if ( !( obj instanceof LoggedMirror ) ) 074 { 075 return false; 076 } 077 LoggedMirror that = (LoggedMirror) obj; 078 return Arrays.equals( keys, that.keys ); 079 } 080 081 @Override 082 public int hashCode() 083 { 084 return Arrays.hashCode( keys ); 085 } 086 087 } 088 089 private static final Logger LOGGER = LoggerFactory.getLogger( DefaultRemoteRepositoryManager.class ); 090 091 private UpdatePolicyAnalyzer updatePolicyAnalyzer; 092 093 private ChecksumPolicyProvider checksumPolicyProvider; 094 095 public DefaultRemoteRepositoryManager() 096 { 097 // enables default constructor 098 } 099 100 @Inject 101 DefaultRemoteRepositoryManager( UpdatePolicyAnalyzer updatePolicyAnalyzer, 102 ChecksumPolicyProvider checksumPolicyProvider ) 103 { 104 setUpdatePolicyAnalyzer( updatePolicyAnalyzer ); 105 setChecksumPolicyProvider( checksumPolicyProvider ); 106 } 107 108 public void initService( ServiceLocator locator ) 109 { 110 setUpdatePolicyAnalyzer( locator.getService( UpdatePolicyAnalyzer.class ) ); 111 setChecksumPolicyProvider( locator.getService( ChecksumPolicyProvider.class ) ); 112 } 113 114 public DefaultRemoteRepositoryManager setUpdatePolicyAnalyzer( UpdatePolicyAnalyzer updatePolicyAnalyzer ) 115 { 116 this.updatePolicyAnalyzer = requireNonNull( updatePolicyAnalyzer, "update policy analyzer cannot be null" ); 117 return this; 118 } 119 120 public DefaultRemoteRepositoryManager setChecksumPolicyProvider( ChecksumPolicyProvider checksumPolicyProvider ) 121 { 122 this.checksumPolicyProvider = requireNonNull( checksumPolicyProvider, "checksum policy provider cannot be null" ); 123 return this; 124 } 125 126 public List<RemoteRepository> aggregateRepositories( RepositorySystemSession session, 127 List<RemoteRepository> dominantRepositories, 128 List<RemoteRepository> recessiveRepositories, 129 boolean recessiveIsRaw ) 130 { 131 if ( recessiveRepositories.isEmpty() ) 132 { 133 return dominantRepositories; 134 } 135 136 MirrorSelector mirrorSelector = session.getMirrorSelector(); 137 AuthenticationSelector authSelector = session.getAuthenticationSelector(); 138 ProxySelector proxySelector = session.getProxySelector(); 139 140 List<RemoteRepository> result = new ArrayList<RemoteRepository>( dominantRepositories ); 141 142 next: for ( RemoteRepository recessiveRepository : recessiveRepositories ) 143 { 144 RemoteRepository repository = recessiveRepository; 145 146 if ( recessiveIsRaw ) 147 { 148 RemoteRepository mirrorRepository = mirrorSelector.getMirror( recessiveRepository ); 149 150 if ( mirrorRepository != null ) 151 { 152 logMirror( session, recessiveRepository, mirrorRepository ); 153 repository = mirrorRepository; 154 } 155 } 156 157 String key = getKey( repository ); 158 159 for ( ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); ) 160 { 161 RemoteRepository dominantRepository = it.next(); 162 163 if ( key.equals( getKey( dominantRepository ) ) ) 164 { 165 if ( !dominantRepository.getMirroredRepositories().isEmpty() 166 && !repository.getMirroredRepositories().isEmpty() ) 167 { 168 RemoteRepository mergedRepository = mergeMirrors( session, dominantRepository, repository ); 169 if ( mergedRepository != dominantRepository ) 170 { 171 it.set( mergedRepository ); 172 } 173 } 174 175 continue next; 176 } 177 } 178 179 if ( recessiveIsRaw ) 180 { 181 RemoteRepository.Builder builder = null; 182 Authentication auth = authSelector.getAuthentication( repository ); 183 if ( auth != null ) 184 { 185 builder = new RemoteRepository.Builder( repository ); 186 builder.setAuthentication( auth ); 187 } 188 Proxy proxy = proxySelector.getProxy( repository ); 189 if ( proxy != null ) 190 { 191 if ( builder == null ) 192 { 193 builder = new RemoteRepository.Builder( repository ); 194 } 195 builder.setProxy( proxy ); 196 } 197 if ( builder != null ) 198 { 199 repository = builder.build(); 200 } 201 } 202 203 result.add( repository ); 204 } 205 206 return result; 207 } 208 209 private void logMirror( RepositorySystemSession session, RemoteRepository original, RemoteRepository mirror ) 210 { 211 if ( !LOGGER.isDebugEnabled() ) 212 { 213 return; 214 } 215 RepositoryCache cache = session.getCache(); 216 if ( cache != null ) 217 { 218 Object key = new LoggedMirror( original, mirror ); 219 if ( cache.get( session, key ) != null ) 220 { 221 return; 222 } 223 cache.put( session, key, Boolean.TRUE ); 224 } 225 LOGGER.debug( "Using mirror {} ({}) for {} ({}).", 226 mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl() ); 227 } 228 229 private String getKey( RemoteRepository repository ) 230 { 231 return repository.getId(); 232 } 233 234 private RemoteRepository mergeMirrors( RepositorySystemSession session, RemoteRepository dominant, 235 RemoteRepository recessive ) 236 { 237 RemoteRepository.Builder merged = null; 238 RepositoryPolicy releases = null, snapshots = null; 239 240 next: for ( RemoteRepository rec : recessive.getMirroredRepositories() ) 241 { 242 String recKey = getKey( rec ); 243 244 for ( RemoteRepository dom : dominant.getMirroredRepositories() ) 245 { 246 if ( recKey.equals( getKey( dom ) ) ) 247 { 248 continue next; 249 } 250 } 251 252 if ( merged == null ) 253 { 254 merged = new RemoteRepository.Builder( dominant ); 255 releases = dominant.getPolicy( false ); 256 snapshots = dominant.getPolicy( true ); 257 } 258 259 releases = merge( session, releases, rec.getPolicy( false ), false ); 260 snapshots = merge( session, snapshots, rec.getPolicy( true ), false ); 261 262 merged.addMirroredRepository( rec ); 263 } 264 265 if ( merged == null ) 266 { 267 return dominant; 268 } 269 return merged.setReleasePolicy( releases ).setSnapshotPolicy( snapshots ).build(); 270 } 271 272 public RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository, boolean releases, 273 boolean snapshots ) 274 { 275 RepositoryPolicy policy1 = releases ? repository.getPolicy( false ) : null; 276 RepositoryPolicy policy2 = snapshots ? repository.getPolicy( true ) : null; 277 RepositoryPolicy policy = merge( session, policy1, policy2, true ); 278 return policy; 279 } 280 281 private RepositoryPolicy merge( RepositorySystemSession session, RepositoryPolicy policy1, 282 RepositoryPolicy policy2, boolean globalPolicy ) 283 { 284 RepositoryPolicy policy; 285 286 if ( policy2 == null ) 287 { 288 if ( globalPolicy ) 289 { 290 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() ); 291 } 292 else 293 { 294 policy = policy1; 295 } 296 } 297 else if ( policy1 == null ) 298 { 299 if ( globalPolicy ) 300 { 301 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() ); 302 } 303 else 304 { 305 policy = policy2; 306 } 307 } 308 else if ( !policy2.isEnabled() ) 309 { 310 if ( globalPolicy ) 311 { 312 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() ); 313 } 314 else 315 { 316 policy = policy1; 317 } 318 } 319 else if ( !policy1.isEnabled() ) 320 { 321 if ( globalPolicy ) 322 { 323 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() ); 324 } 325 else 326 { 327 policy = policy2; 328 } 329 } 330 else 331 { 332 String checksums = session.getChecksumPolicy(); 333 if ( globalPolicy && !StringUtils.isEmpty( checksums ) ) 334 { 335 // use global override 336 } 337 else 338 { 339 checksums = 340 checksumPolicyProvider.getEffectiveChecksumPolicy( session, policy1.getChecksumPolicy(), 341 policy2.getChecksumPolicy() ); 342 } 343 344 String updates = session.getUpdatePolicy(); 345 if ( globalPolicy && !StringUtils.isEmpty( updates ) ) 346 { 347 // use global override 348 } 349 else 350 { 351 updates = 352 updatePolicyAnalyzer.getEffectiveUpdatePolicy( session, policy1.getUpdatePolicy(), 353 policy2.getUpdatePolicy() ); 354 } 355 356 policy = new RepositoryPolicy( true, updates, checksums ); 357 } 358 359 return policy; 360 } 361 362 private RepositoryPolicy merge( RepositoryPolicy policy, String updates, String checksums ) 363 { 364 if ( policy != null ) 365 { 366 if ( StringUtils.isEmpty( updates ) ) 367 { 368 updates = policy.getUpdatePolicy(); 369 } 370 if ( StringUtils.isEmpty( checksums ) ) 371 { 372 checksums = policy.getChecksumPolicy(); 373 } 374 if ( !policy.getUpdatePolicy().equals( updates ) || !policy.getChecksumPolicy().equals( checksums ) ) 375 { 376 policy = new RepositoryPolicy( policy.isEnabled(), updates, checksums ); 377 } 378 } 379 return policy; 380 } 381 382}