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