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; 026 027import javax.inject.Inject; 028import javax.inject.Named; 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.eclipse.aether.spi.locator.Service; 043import org.eclipse.aether.spi.locator.ServiceLocator; 044import org.eclipse.aether.spi.log.Logger; 045import org.eclipse.aether.spi.log.LoggerFactory; 046import org.eclipse.aether.spi.log.NullLoggerFactory; 047import org.eclipse.aether.util.StringUtils; 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 public 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 Logger logger = NullLoggerFactory.LOGGER; 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, LoggerFactory loggerFactory ) 103 { 104 setUpdatePolicyAnalyzer( updatePolicyAnalyzer ); 105 setChecksumPolicyProvider( checksumPolicyProvider ); 106 setLoggerFactory( loggerFactory ); 107 } 108 109 public void initService( ServiceLocator locator ) 110 { 111 setLoggerFactory( locator.getService( LoggerFactory.class ) ); 112 setUpdatePolicyAnalyzer( locator.getService( UpdatePolicyAnalyzer.class ) ); 113 setChecksumPolicyProvider( locator.getService( ChecksumPolicyProvider.class ) ); 114 } 115 116 public DefaultRemoteRepositoryManager setLoggerFactory( LoggerFactory loggerFactory ) 117 { 118 this.logger = NullLoggerFactory.getSafeLogger( loggerFactory, getClass() ); 119 return this; 120 } 121 122 public DefaultRemoteRepositoryManager setUpdatePolicyAnalyzer( UpdatePolicyAnalyzer updatePolicyAnalyzer ) 123 { 124 if ( updatePolicyAnalyzer == null ) 125 { 126 throw new IllegalArgumentException( "update policy analyzer has not been specified" ); 127 } 128 this.updatePolicyAnalyzer = updatePolicyAnalyzer; 129 return this; 130 } 131 132 public DefaultRemoteRepositoryManager setChecksumPolicyProvider( ChecksumPolicyProvider checksumPolicyProvider ) 133 { 134 if ( checksumPolicyProvider == null ) 135 { 136 throw new IllegalArgumentException( "checksum policy provider has not been specified" ); 137 } 138 this.checksumPolicyProvider = checksumPolicyProvider; 139 return this; 140 } 141 142 public List<RemoteRepository> aggregateRepositories( RepositorySystemSession session, 143 List<RemoteRepository> dominantRepositories, 144 List<RemoteRepository> recessiveRepositories, 145 boolean recessiveIsRaw ) 146 { 147 if ( recessiveRepositories.isEmpty() ) 148 { 149 return dominantRepositories; 150 } 151 152 MirrorSelector mirrorSelector = session.getMirrorSelector(); 153 AuthenticationSelector authSelector = session.getAuthenticationSelector(); 154 ProxySelector proxySelector = session.getProxySelector(); 155 156 List<RemoteRepository> result = new ArrayList<RemoteRepository>( dominantRepositories ); 157 158 next: for ( RemoteRepository recessiveRepository : recessiveRepositories ) 159 { 160 RemoteRepository repository = recessiveRepository; 161 162 if ( recessiveIsRaw ) 163 { 164 RemoteRepository mirrorRepository = mirrorSelector.getMirror( recessiveRepository ); 165 166 if ( mirrorRepository != null ) 167 { 168 logMirror( session, recessiveRepository, mirrorRepository ); 169 repository = mirrorRepository; 170 } 171 } 172 173 String key = getKey( repository ); 174 175 for ( ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); ) 176 { 177 RemoteRepository dominantRepository = it.next(); 178 179 if ( key.equals( getKey( dominantRepository ) ) ) 180 { 181 if ( !dominantRepository.getMirroredRepositories().isEmpty() 182 && !repository.getMirroredRepositories().isEmpty() ) 183 { 184 RemoteRepository mergedRepository = mergeMirrors( session, dominantRepository, repository ); 185 if ( mergedRepository != dominantRepository ) 186 { 187 it.set( mergedRepository ); 188 } 189 } 190 191 continue next; 192 } 193 } 194 195 if ( recessiveIsRaw ) 196 { 197 RemoteRepository.Builder builder = null; 198 Authentication auth = authSelector.getAuthentication( repository ); 199 if ( auth != null ) 200 { 201 builder = new RemoteRepository.Builder( repository ); 202 builder.setAuthentication( auth ); 203 } 204 Proxy proxy = proxySelector.getProxy( repository ); 205 if ( proxy != null ) 206 { 207 if ( builder == null ) 208 { 209 builder = new RemoteRepository.Builder( repository ); 210 } 211 builder.setProxy( proxy ); 212 } 213 if ( builder != null ) 214 { 215 repository = builder.build(); 216 } 217 } 218 219 result.add( repository ); 220 } 221 222 return result; 223 } 224 225 private void logMirror( RepositorySystemSession session, RemoteRepository original, RemoteRepository mirror ) 226 { 227 if ( !logger.isDebugEnabled() ) 228 { 229 return; 230 } 231 RepositoryCache cache = session.getCache(); 232 if ( cache != null ) 233 { 234 Object key = new LoggedMirror( original, mirror ); 235 if ( cache.get( session, key ) != null ) 236 { 237 return; 238 } 239 cache.put( session, key, Boolean.TRUE ); 240 } 241 logger.debug( "Using mirror " + mirror.getId() + " (" + mirror.getUrl() + ") for " + original.getId() + " (" 242 + original.getUrl() + ")." ); 243 } 244 245 private String getKey( RemoteRepository repository ) 246 { 247 return repository.getId(); 248 } 249 250 private RemoteRepository mergeMirrors( RepositorySystemSession session, RemoteRepository dominant, 251 RemoteRepository recessive ) 252 { 253 RemoteRepository.Builder merged = null; 254 RepositoryPolicy releases = null, snapshots = null; 255 256 next: for ( RemoteRepository rec : recessive.getMirroredRepositories() ) 257 { 258 String recKey = getKey( rec ); 259 260 for ( RemoteRepository dom : dominant.getMirroredRepositories() ) 261 { 262 if ( recKey.equals( getKey( dom ) ) ) 263 { 264 continue next; 265 } 266 } 267 268 if ( merged == null ) 269 { 270 merged = new RemoteRepository.Builder( dominant ); 271 releases = dominant.getPolicy( false ); 272 snapshots = dominant.getPolicy( true ); 273 } 274 275 releases = merge( session, releases, rec.getPolicy( false ), false ); 276 snapshots = merge( session, snapshots, rec.getPolicy( true ), false ); 277 278 merged.addMirroredRepository( rec ); 279 } 280 281 if ( merged == null ) 282 { 283 return dominant; 284 } 285 return merged.setReleasePolicy( releases ).setSnapshotPolicy( snapshots ).build(); 286 } 287 288 public RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository, boolean releases, 289 boolean snapshots ) 290 { 291 RepositoryPolicy policy1 = releases ? repository.getPolicy( false ) : null; 292 RepositoryPolicy policy2 = snapshots ? repository.getPolicy( true ) : null; 293 RepositoryPolicy policy = merge( session, policy1, policy2, true ); 294 return policy; 295 } 296 297 private RepositoryPolicy merge( RepositorySystemSession session, RepositoryPolicy policy1, 298 RepositoryPolicy policy2, boolean globalPolicy ) 299 { 300 RepositoryPolicy policy; 301 302 if ( policy2 == null ) 303 { 304 if ( globalPolicy ) 305 { 306 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() ); 307 } 308 else 309 { 310 policy = policy1; 311 } 312 } 313 else if ( policy1 == null ) 314 { 315 if ( globalPolicy ) 316 { 317 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() ); 318 } 319 else 320 { 321 policy = policy2; 322 } 323 } 324 else if ( !policy2.isEnabled() ) 325 { 326 if ( globalPolicy ) 327 { 328 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() ); 329 } 330 else 331 { 332 policy = policy1; 333 } 334 } 335 else if ( !policy1.isEnabled() ) 336 { 337 if ( globalPolicy ) 338 { 339 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() ); 340 } 341 else 342 { 343 policy = policy2; 344 } 345 } 346 else 347 { 348 String checksums = session.getChecksumPolicy(); 349 if ( globalPolicy && !StringUtils.isEmpty( checksums ) ) 350 { 351 // use global override 352 } 353 else 354 { 355 checksums = 356 checksumPolicyProvider.getEffectiveChecksumPolicy( session, policy1.getChecksumPolicy(), 357 policy2.getChecksumPolicy() ); 358 } 359 360 String updates = session.getUpdatePolicy(); 361 if ( globalPolicy && !StringUtils.isEmpty( updates ) ) 362 { 363 // use global override 364 } 365 else 366 { 367 updates = 368 updatePolicyAnalyzer.getEffectiveUpdatePolicy( session, policy1.getUpdatePolicy(), 369 policy2.getUpdatePolicy() ); 370 } 371 372 policy = new RepositoryPolicy( true, updates, checksums ); 373 } 374 375 return policy; 376 } 377 378 private RepositoryPolicy merge( RepositoryPolicy policy, String updates, String checksums ) 379 { 380 if ( policy != null ) 381 { 382 if ( StringUtils.isEmpty( updates ) ) 383 { 384 updates = policy.getUpdatePolicy(); 385 } 386 if ( StringUtils.isEmpty( checksums ) ) 387 { 388 checksums = policy.getChecksumPolicy(); 389 } 390 if ( !policy.getUpdatePolicy().equals( updates ) || !policy.getChecksumPolicy().equals( checksums ) ) 391 { 392 policy = new RepositoryPolicy( policy.isEnabled(), updates, checksums ); 393 } 394 } 395 return policy; 396 } 397 398}