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