001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.eclipse.aether.internal.impl.session; 020 021import java.nio.file.Path; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.Collection; 025import java.util.HashMap; 026import java.util.Map; 027import java.util.function.Supplier; 028 029import org.eclipse.aether.DefaultSessionData; 030import org.eclipse.aether.RepositoryCache; 031import org.eclipse.aether.RepositoryListener; 032import org.eclipse.aether.RepositorySystem; 033import org.eclipse.aether.RepositorySystemSession; 034import org.eclipse.aether.RepositorySystemSession.CloseableSession; 035import org.eclipse.aether.RepositorySystemSession.SessionBuilder; 036import org.eclipse.aether.SessionData; 037import org.eclipse.aether.artifact.ArtifactTypeRegistry; 038import org.eclipse.aether.collection.DependencyGraphTransformer; 039import org.eclipse.aether.collection.DependencyManager; 040import org.eclipse.aether.collection.DependencySelector; 041import org.eclipse.aether.collection.DependencyTraverser; 042import org.eclipse.aether.collection.VersionFilter; 043import org.eclipse.aether.impl.RepositorySystemLifecycle; 044import org.eclipse.aether.repository.AuthenticationSelector; 045import org.eclipse.aether.repository.LocalRepository; 046import org.eclipse.aether.repository.LocalRepositoryManager; 047import org.eclipse.aether.repository.MirrorSelector; 048import org.eclipse.aether.repository.ProxySelector; 049import org.eclipse.aether.repository.RemoteRepository; 050import org.eclipse.aether.repository.WorkspaceReader; 051import org.eclipse.aether.resolution.ArtifactDescriptorPolicy; 052import org.eclipse.aether.resolution.ResolutionErrorPolicy; 053import org.eclipse.aether.scope.ScopeManager; 054import org.eclipse.aether.transfer.TransferListener; 055 056import static java.util.Objects.requireNonNull; 057import static java.util.stream.Collectors.toList; 058 059/** 060 * A default implementation of session builder. Is not immutable nor thread-safe. 061 */ 062public final class DefaultSessionBuilder implements SessionBuilder { 063 private static final MirrorSelector NULL_MIRROR_SELECTOR = r -> null; 064 065 private static final ProxySelector PASS_THROUGH_PROXY_SELECTOR = RemoteRepository::getProxy; 066 067 private static final AuthenticationSelector PASS_THROUGH_AUTHENTICATION_SELECTOR = 068 RemoteRepository::getAuthentication; 069 070 private static final ArtifactTypeRegistry NULL_ARTIFACT_TYPE_REGISTRY = t -> null; 071 072 private static final Supplier<SessionData> DEFAULT_SESSION_DATA_SUPPLIER = DefaultSessionData::new; 073 074 private static final Supplier<RepositoryCache> DEFAULT_REPOSITORY_CACHE_SUPPLIER = () -> null; 075 076 private final RepositorySystem repositorySystem; 077 078 private final RepositorySystemLifecycle repositorySystemLifecycle; 079 080 private final Supplier<String> sessionIdSupplier; 081 082 private boolean offline; 083 084 private boolean ignoreArtifactDescriptorRepositories; 085 086 private ResolutionErrorPolicy resolutionErrorPolicy; 087 088 private ArtifactDescriptorPolicy artifactDescriptorPolicy; 089 090 private String checksumPolicy; 091 092 private String artifactUpdatePolicy; 093 094 private String metadataUpdatePolicy; 095 096 private LocalRepositoryManager localRepositoryManager; 097 098 private Collection<LocalRepository> localRepositories; 099 100 private WorkspaceReader workspaceReader; 101 102 private final ArrayList<RepositoryListener> repositoryListener = new ArrayList<>(); 103 104 private final ArrayList<TransferListener> transferListener = new ArrayList<>(); 105 106 private Map<String, String> systemProperties = new HashMap<>(); 107 108 private Map<String, String> userProperties = new HashMap<>(); 109 110 private Map<String, Object> configProperties = new HashMap<>(); 111 112 private MirrorSelector mirrorSelector = NULL_MIRROR_SELECTOR; 113 114 private ProxySelector proxySelector = PASS_THROUGH_PROXY_SELECTOR; 115 116 private AuthenticationSelector authenticationSelector = PASS_THROUGH_AUTHENTICATION_SELECTOR; 117 118 private ArtifactTypeRegistry artifactTypeRegistry = NULL_ARTIFACT_TYPE_REGISTRY; 119 120 private DependencyTraverser dependencyTraverser; 121 122 private DependencyManager dependencyManager; 123 124 private DependencySelector dependencySelector; 125 126 private VersionFilter versionFilter; 127 128 private DependencyGraphTransformer dependencyGraphTransformer; 129 130 private Supplier<SessionData> sessionDataSupplier = DEFAULT_SESSION_DATA_SUPPLIER; 131 132 private Supplier<RepositoryCache> repositoryCacheSupplier = DEFAULT_REPOSITORY_CACHE_SUPPLIER; 133 134 private ScopeManager scopeManager; 135 136 private final ArrayList<Runnable> onSessionCloseHandlers = new ArrayList<>(); 137 138 /** 139 * Constructor for "top level" builders. 140 */ 141 public DefaultSessionBuilder( 142 RepositorySystem repositorySystem, 143 RepositorySystemLifecycle repositorySystemLifecycle, 144 Supplier<String> sessionIdSupplier) { 145 this.repositorySystem = requireNonNull(repositorySystem); 146 this.repositorySystemLifecycle = requireNonNull(repositorySystemLifecycle); 147 this.sessionIdSupplier = requireNonNull(sessionIdSupplier); 148 } 149 150 @Override 151 public DefaultSessionBuilder setOffline(boolean offline) { 152 this.offline = offline; 153 return this; 154 } 155 156 @Override 157 public DefaultSessionBuilder setIgnoreArtifactDescriptorRepositories(boolean ignoreArtifactDescriptorRepositories) { 158 this.ignoreArtifactDescriptorRepositories = ignoreArtifactDescriptorRepositories; 159 return this; 160 } 161 162 @Override 163 public DefaultSessionBuilder setResolutionErrorPolicy(ResolutionErrorPolicy resolutionErrorPolicy) { 164 this.resolutionErrorPolicy = resolutionErrorPolicy; 165 return this; 166 } 167 168 @Override 169 public DefaultSessionBuilder setArtifactDescriptorPolicy(ArtifactDescriptorPolicy artifactDescriptorPolicy) { 170 this.artifactDescriptorPolicy = artifactDescriptorPolicy; 171 return this; 172 } 173 174 @Override 175 public DefaultSessionBuilder setChecksumPolicy(String checksumPolicy) { 176 this.checksumPolicy = checksumPolicy; 177 return this; 178 } 179 180 @Override 181 public DefaultSessionBuilder setUpdatePolicy(String updatePolicy) { 182 setArtifactUpdatePolicy(updatePolicy); 183 setMetadataUpdatePolicy(updatePolicy); 184 return this; 185 } 186 187 @Override 188 public DefaultSessionBuilder setArtifactUpdatePolicy(String artifactUpdatePolicy) { 189 this.artifactUpdatePolicy = artifactUpdatePolicy; 190 return this; 191 } 192 193 @Override 194 public DefaultSessionBuilder setMetadataUpdatePolicy(String metadataUpdatePolicy) { 195 this.metadataUpdatePolicy = metadataUpdatePolicy; 196 return this; 197 } 198 199 @Override 200 public DefaultSessionBuilder setLocalRepositoryManager(LocalRepositoryManager localRepositoryManager) { 201 this.localRepositoryManager = localRepositoryManager; 202 return this; 203 } 204 205 @Override 206 public DefaultSessionBuilder setWorkspaceReader(WorkspaceReader workspaceReader) { 207 this.workspaceReader = workspaceReader; 208 return this; 209 } 210 211 @Override 212 public DefaultSessionBuilder setRepositoryListener(RepositoryListener repositoryListener) { 213 this.repositoryListener.clear(); 214 if (repositoryListener != null) { 215 this.repositoryListener.add(repositoryListener); 216 } 217 return this; 218 } 219 220 @Override 221 public DefaultSessionBuilder setTransferListener(TransferListener transferListener) { 222 this.transferListener.clear(); 223 if (transferListener != null) { 224 this.transferListener.add(transferListener); 225 } 226 return this; 227 } 228 229 @Override 230 public DefaultSessionBuilder setSystemProperties(Map<?, ?> systemProperties) { 231 this.systemProperties = copySafe(systemProperties, String.class); 232 return this; 233 } 234 235 @Override 236 public DefaultSessionBuilder setSystemProperty(String key, String value) { 237 if (value != null) { 238 systemProperties.put(key, value); 239 } else { 240 systemProperties.remove(key); 241 } 242 return this; 243 } 244 245 @Override 246 public DefaultSessionBuilder setUserProperties(Map<?, ?> userProperties) { 247 this.userProperties = copySafe(userProperties, String.class); 248 return this; 249 } 250 251 @Override 252 public DefaultSessionBuilder setUserProperty(String key, String value) { 253 if (value != null) { 254 userProperties.put(key, value); 255 } else { 256 userProperties.remove(key); 257 } 258 return this; 259 } 260 261 @Override 262 public DefaultSessionBuilder setConfigProperties(Map<?, ?> configProperties) { 263 this.configProperties = copySafe(configProperties, Object.class); 264 return this; 265 } 266 267 @Override 268 public DefaultSessionBuilder setConfigProperty(String key, Object value) { 269 if (value != null) { 270 configProperties.put(key, value); 271 } else { 272 configProperties.remove(key); 273 } 274 return this; 275 } 276 277 @Override 278 public DefaultSessionBuilder setMirrorSelector(MirrorSelector mirrorSelector) { 279 this.mirrorSelector = mirrorSelector; 280 if (this.mirrorSelector == null) { 281 this.mirrorSelector = NULL_MIRROR_SELECTOR; 282 } 283 return this; 284 } 285 286 @Override 287 public DefaultSessionBuilder setProxySelector(ProxySelector proxySelector) { 288 this.proxySelector = proxySelector; 289 if (this.proxySelector == null) { 290 this.proxySelector = PASS_THROUGH_PROXY_SELECTOR; 291 } 292 return this; 293 } 294 295 @Override 296 public DefaultSessionBuilder setAuthenticationSelector(AuthenticationSelector authenticationSelector) { 297 this.authenticationSelector = authenticationSelector; 298 if (this.authenticationSelector == null) { 299 this.authenticationSelector = PASS_THROUGH_AUTHENTICATION_SELECTOR; 300 } 301 return this; 302 } 303 304 @Override 305 public DefaultSessionBuilder setArtifactTypeRegistry(ArtifactTypeRegistry artifactTypeRegistry) { 306 this.artifactTypeRegistry = artifactTypeRegistry; 307 if (this.artifactTypeRegistry == null) { 308 this.artifactTypeRegistry = NULL_ARTIFACT_TYPE_REGISTRY; 309 } 310 return this; 311 } 312 313 @Override 314 public DefaultSessionBuilder setDependencyTraverser(DependencyTraverser dependencyTraverser) { 315 this.dependencyTraverser = dependencyTraverser; 316 return this; 317 } 318 319 @Override 320 public DefaultSessionBuilder setDependencyManager(DependencyManager dependencyManager) { 321 this.dependencyManager = dependencyManager; 322 return this; 323 } 324 325 @Override 326 public DefaultSessionBuilder setDependencySelector(DependencySelector dependencySelector) { 327 this.dependencySelector = dependencySelector; 328 return this; 329 } 330 331 @Override 332 public DefaultSessionBuilder setVersionFilter(VersionFilter versionFilter) { 333 this.versionFilter = versionFilter; 334 return this; 335 } 336 337 @Override 338 public DefaultSessionBuilder setDependencyGraphTransformer(DependencyGraphTransformer dependencyGraphTransformer) { 339 this.dependencyGraphTransformer = dependencyGraphTransformer; 340 return this; 341 } 342 343 @Override 344 public DefaultSessionBuilder setData(SessionData data) { 345 return setSessionDataSupplier(() -> data); 346 } 347 348 @Override 349 public DefaultSessionBuilder setSessionDataSupplier(Supplier<SessionData> dataSupplier) { 350 requireNonNull(dataSupplier, "null dataSupplier"); 351 this.sessionDataSupplier = dataSupplier; 352 return this; 353 } 354 355 @Override 356 public DefaultSessionBuilder setCache(RepositoryCache cache) { 357 return setRepositoryCacheSupplier(() -> cache); 358 } 359 360 @Override 361 public DefaultSessionBuilder setScopeManager(ScopeManager scopeManager) { 362 this.scopeManager = scopeManager; 363 return this; 364 } 365 366 @Override 367 public SessionBuilder addOnSessionEndedHandler(Runnable handler) { 368 requireNonNull(handler, "null handler"); 369 onSessionCloseHandlers.add(handler); 370 return this; 371 } 372 373 @Override 374 public DefaultSessionBuilder setRepositoryCacheSupplier(Supplier<RepositoryCache> cacheSupplier) { 375 requireNonNull(cacheSupplier, "null cacheSupplier"); 376 this.repositoryCacheSupplier = cacheSupplier; 377 return this; 378 } 379 380 @Override 381 public SessionBuilder withLocalRepositoryBaseDirectories(Path... baseDirectories) { 382 return withLocalRepositoryBaseDirectories(Arrays.asList(baseDirectories)); 383 } 384 385 @Override 386 public SessionBuilder withLocalRepositoryBaseDirectories(Collection<Path> baseDirectories) { 387 requireNonNull(baseDirectories, "null baseDirectories"); 388 return withLocalRepositories( 389 baseDirectories.stream().map(LocalRepository::new).collect(toList())); 390 } 391 392 @Override 393 public SessionBuilder withLocalRepositories(LocalRepository... localRepositories) { 394 return withLocalRepositories(Arrays.asList(localRepositories)); 395 } 396 397 @Override 398 public SessionBuilder withLocalRepositories(Collection<LocalRepository> localRepositories) { 399 requireNonNull(localRepositories, "null localRepositories"); 400 this.localRepositories = localRepositories; 401 return this; 402 } 403 404 @Override 405 public SessionBuilder withRepositoryListener(RepositoryListener... repositoryListeners) { 406 return withRepositoryListener(Arrays.asList(repositoryListeners)); 407 } 408 409 @Override 410 public SessionBuilder withRepositoryListener(Collection<RepositoryListener> repositoryListeners) { 411 this.repositoryListener.addAll(repositoryListeners); 412 return this; 413 } 414 415 @Override 416 public SessionBuilder withTransferListener(TransferListener... transferListeners) { 417 return withTransferListener(Arrays.asList(transferListeners)); 418 } 419 420 @Override 421 public SessionBuilder withTransferListener(Collection<TransferListener> transferListeners) { 422 this.transferListener.addAll(transferListeners); 423 return this; 424 } 425 426 @Override 427 public SessionBuilder withRepositorySystemSession(RepositorySystemSession session) { 428 requireNonNull(session, "repository system session cannot be null"); 429 setOffline(session.isOffline()); 430 setIgnoreArtifactDescriptorRepositories(session.isIgnoreArtifactDescriptorRepositories()); 431 setResolutionErrorPolicy(session.getResolutionErrorPolicy()); 432 setArtifactDescriptorPolicy(session.getArtifactDescriptorPolicy()); 433 setChecksumPolicy(session.getChecksumPolicy()); 434 setUpdatePolicy(session.getUpdatePolicy()); 435 setMetadataUpdatePolicy(session.getMetadataUpdatePolicy()); 436 setLocalRepositoryManager(session.getLocalRepositoryManager()); 437 setWorkspaceReader(session.getWorkspaceReader()); 438 setRepositoryListener(session.getRepositoryListener()); 439 setTransferListener(session.getTransferListener()); 440 setSystemProperties(session.getSystemProperties()); 441 setUserProperties(session.getUserProperties()); 442 setConfigProperties(session.getConfigProperties()); 443 setMirrorSelector(session.getMirrorSelector()); 444 setProxySelector(session.getProxySelector()); 445 setAuthenticationSelector(session.getAuthenticationSelector()); 446 setArtifactTypeRegistry(session.getArtifactTypeRegistry()); 447 setDependencyTraverser(session.getDependencyTraverser()); 448 setDependencyManager(session.getDependencyManager()); 449 setDependencySelector(session.getDependencySelector()); 450 setVersionFilter(session.getVersionFilter()); 451 setDependencyGraphTransformer(session.getDependencyGraphTransformer()); 452 setData(session.getData()); 453 setCache(session.getCache()); 454 return this; 455 } 456 457 @Override 458 public CloseableSession build() { 459 return new DefaultCloseableSession( 460 sessionIdSupplier.get(), 461 offline, 462 ignoreArtifactDescriptorRepositories, 463 resolutionErrorPolicy, 464 artifactDescriptorPolicy, 465 checksumPolicy, 466 artifactUpdatePolicy, 467 metadataUpdatePolicy, 468 localRepositoryManager, 469 localRepositories, 470 workspaceReader, 471 repositoryListener, 472 transferListener, 473 copySafe(systemProperties, String.class), 474 copySafe(userProperties, String.class), 475 copySafe(configProperties, Object.class), 476 mirrorSelector, 477 proxySelector, 478 authenticationSelector, 479 artifactTypeRegistry, 480 dependencyTraverser, 481 dependencyManager, 482 dependencySelector, 483 versionFilter, 484 dependencyGraphTransformer, 485 sessionDataSupplier.get(), 486 repositoryCacheSupplier.get(), 487 scopeManager, 488 onSessionCloseHandlers, 489 repositorySystem, 490 repositorySystemLifecycle); 491 } 492 493 @SuppressWarnings("checkstyle:magicnumber") 494 private static <T> Map<String, T> copySafe(Map<?, ?> table, Class<T> valueType) { 495 Map<String, T> map; 496 if (table == null || table.isEmpty()) { 497 map = new HashMap<>(); 498 } else { 499 map = new HashMap<>((int) (table.size() / 0.75f) + 1); 500 for (Map.Entry<?, ?> entry : table.entrySet()) { 501 Object key = entry.getKey(); 502 if (key instanceof String) { 503 Object value = entry.getValue(); 504 if (valueType.isInstance(value)) { 505 map.put(key.toString(), valueType.cast(value)); 506 } 507 } 508 } 509 } 510 return map; 511 } 512}