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 requireNonNull( session, "session cannot be null" ); 135 requireNonNull( dominantRepositories, "dominantRepositories cannot be null" ); 136 requireNonNull( recessiveRepositories, "recessiveRepositories cannot be null" ); 137 if ( recessiveRepositories.isEmpty() ) 138 { 139 return dominantRepositories; 140 } 141 142 MirrorSelector mirrorSelector = session.getMirrorSelector(); 143 AuthenticationSelector authSelector = session.getAuthenticationSelector(); 144 ProxySelector proxySelector = session.getProxySelector(); 145 146 List<RemoteRepository> result = new ArrayList<>( dominantRepositories ); 147 148 next: for ( RemoteRepository recessiveRepository : recessiveRepositories ) 149 { 150 RemoteRepository repository = recessiveRepository; 151 152 if ( recessiveIsRaw ) 153 { 154 RemoteRepository mirrorRepository = mirrorSelector.getMirror( recessiveRepository ); 155 156 if ( mirrorRepository != null ) 157 { 158 logMirror( session, recessiveRepository, mirrorRepository ); 159 repository = mirrorRepository; 160 } 161 } 162 163 String key = getKey( repository ); 164 165 for ( ListIterator<RemoteRepository> it = result.listIterator(); it.hasNext(); ) 166 { 167 RemoteRepository dominantRepository = it.next(); 168 169 if ( key.equals( getKey( dominantRepository ) ) ) 170 { 171 if ( !dominantRepository.getMirroredRepositories().isEmpty() 172 && !repository.getMirroredRepositories().isEmpty() ) 173 { 174 RemoteRepository mergedRepository = mergeMirrors( session, dominantRepository, repository ); 175 if ( mergedRepository != dominantRepository ) 176 { 177 it.set( mergedRepository ); 178 } 179 } 180 181 continue next; 182 } 183 } 184 185 if ( recessiveIsRaw ) 186 { 187 RemoteRepository.Builder builder = null; 188 Authentication auth = authSelector.getAuthentication( repository ); 189 if ( auth != null ) 190 { 191 builder = new RemoteRepository.Builder( repository ); 192 builder.setAuthentication( auth ); 193 } 194 Proxy proxy = proxySelector.getProxy( repository ); 195 if ( proxy != null ) 196 { 197 if ( builder == null ) 198 { 199 builder = new RemoteRepository.Builder( repository ); 200 } 201 builder.setProxy( proxy ); 202 } 203 if ( builder != null ) 204 { 205 repository = builder.build(); 206 } 207 } 208 209 result.add( repository ); 210 } 211 212 return result; 213 } 214 215 private void logMirror( RepositorySystemSession session, RemoteRepository original, RemoteRepository mirror ) 216 { 217 if ( !LOGGER.isDebugEnabled() ) 218 { 219 return; 220 } 221 RepositoryCache cache = session.getCache(); 222 if ( cache != null ) 223 { 224 Object key = new LoggedMirror( original, mirror ); 225 if ( cache.get( session, key ) != null ) 226 { 227 return; 228 } 229 cache.put( session, key, Boolean.TRUE ); 230 } 231 LOGGER.debug( "Using mirror {} ({}) for {} ({}).", 232 mirror.getId(), mirror.getUrl(), original.getId(), original.getUrl() ); 233 } 234 235 private String getKey( RemoteRepository repository ) 236 { 237 return repository.getId(); 238 } 239 240 private RemoteRepository mergeMirrors( RepositorySystemSession session, RemoteRepository dominant, 241 RemoteRepository recessive ) 242 { 243 RemoteRepository.Builder merged = null; 244 RepositoryPolicy releases = null, snapshots = null; 245 246 next: for ( RemoteRepository rec : recessive.getMirroredRepositories() ) 247 { 248 String recKey = getKey( rec ); 249 250 for ( RemoteRepository dom : dominant.getMirroredRepositories() ) 251 { 252 if ( recKey.equals( getKey( dom ) ) ) 253 { 254 continue next; 255 } 256 } 257 258 if ( merged == null ) 259 { 260 merged = new RemoteRepository.Builder( dominant ); 261 releases = dominant.getPolicy( false ); 262 snapshots = dominant.getPolicy( true ); 263 } 264 265 releases = merge( session, releases, rec.getPolicy( false ), false ); 266 snapshots = merge( session, snapshots, rec.getPolicy( true ), false ); 267 268 merged.addMirroredRepository( rec ); 269 } 270 271 if ( merged == null ) 272 { 273 return dominant; 274 } 275 return merged.setReleasePolicy( releases ).setSnapshotPolicy( snapshots ).build(); 276 } 277 278 public RepositoryPolicy getPolicy( RepositorySystemSession session, RemoteRepository repository, boolean releases, 279 boolean snapshots ) 280 { 281 requireNonNull( session, "session cannot be null" ); 282 requireNonNull( repository, "repository cannot be null" ); 283 RepositoryPolicy policy1 = releases ? repository.getPolicy( false ) : null; 284 RepositoryPolicy policy2 = snapshots ? repository.getPolicy( true ) : null; 285 return merge( session, policy1, policy2, true ); 286 } 287 288 private RepositoryPolicy merge( RepositorySystemSession session, RepositoryPolicy policy1, 289 RepositoryPolicy policy2, boolean globalPolicy ) 290 { 291 RepositoryPolicy policy; 292 293 if ( policy2 == null ) 294 { 295 if ( globalPolicy ) 296 { 297 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() ); 298 } 299 else 300 { 301 policy = policy1; 302 } 303 } 304 else if ( policy1 == null ) 305 { 306 if ( globalPolicy ) 307 { 308 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() ); 309 } 310 else 311 { 312 policy = policy2; 313 } 314 } 315 else if ( !policy2.isEnabled() ) 316 { 317 if ( globalPolicy ) 318 { 319 policy = merge( policy1, session.getUpdatePolicy(), session.getChecksumPolicy() ); 320 } 321 else 322 { 323 policy = policy1; 324 } 325 } 326 else if ( !policy1.isEnabled() ) 327 { 328 if ( globalPolicy ) 329 { 330 policy = merge( policy2, session.getUpdatePolicy(), session.getChecksumPolicy() ); 331 } 332 else 333 { 334 policy = policy2; 335 } 336 } 337 else 338 { 339 String checksums = session.getChecksumPolicy(); 340 //noinspection StatementWithEmptyBody 341 if ( globalPolicy && !StringUtils.isEmpty( checksums ) ) 342 { 343 // use global override 344 } 345 else 346 { 347 checksums = 348 checksumPolicyProvider.getEffectiveChecksumPolicy( session, policy1.getChecksumPolicy(), 349 policy2.getChecksumPolicy() ); 350 } 351 352 String updates = session.getUpdatePolicy(); 353 //noinspection StatementWithEmptyBody 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}