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; 020 021import javax.inject.Inject; 022import javax.inject.Named; 023import javax.inject.Singleton; 024 025import java.util.ArrayList; 026import java.util.Collection; 027import java.util.List; 028import java.util.Objects; 029import java.util.concurrent.atomic.AtomicBoolean; 030import java.util.function.Consumer; 031import java.util.stream.Collectors; 032 033import org.eclipse.aether.ConfigurationProperties; 034import org.eclipse.aether.RepositorySystem; 035import org.eclipse.aether.RepositorySystemSession; 036import org.eclipse.aether.RequestTrace; 037import org.eclipse.aether.SyncContext; 038import org.eclipse.aether.artifact.Artifact; 039import org.eclipse.aether.collection.CollectRequest; 040import org.eclipse.aether.collection.CollectResult; 041import org.eclipse.aether.collection.DependencyCollectionException; 042import org.eclipse.aether.deployment.DeployRequest; 043import org.eclipse.aether.deployment.DeployResult; 044import org.eclipse.aether.deployment.DeploymentException; 045import org.eclipse.aether.graph.DependencyFilter; 046import org.eclipse.aether.graph.DependencyNode; 047import org.eclipse.aether.graph.DependencyVisitor; 048import org.eclipse.aether.impl.ArtifactDescriptorReader; 049import org.eclipse.aether.impl.ArtifactResolver; 050import org.eclipse.aether.impl.DependencyCollector; 051import org.eclipse.aether.impl.Deployer; 052import org.eclipse.aether.impl.Installer; 053import org.eclipse.aether.impl.LocalRepositoryProvider; 054import org.eclipse.aether.impl.MetadataResolver; 055import org.eclipse.aether.impl.RemoteRepositoryManager; 056import org.eclipse.aether.impl.RepositorySystemLifecycle; 057import org.eclipse.aether.impl.VersionRangeResolver; 058import org.eclipse.aether.impl.VersionResolver; 059import org.eclipse.aether.installation.InstallRequest; 060import org.eclipse.aether.installation.InstallResult; 061import org.eclipse.aether.installation.InstallationException; 062import org.eclipse.aether.repository.Authentication; 063import org.eclipse.aether.repository.LocalRepository; 064import org.eclipse.aether.repository.LocalRepositoryManager; 065import org.eclipse.aether.repository.NoLocalRepositoryManagerException; 066import org.eclipse.aether.repository.Proxy; 067import org.eclipse.aether.repository.RemoteRepository; 068import org.eclipse.aether.resolution.ArtifactDescriptorException; 069import org.eclipse.aether.resolution.ArtifactDescriptorRequest; 070import org.eclipse.aether.resolution.ArtifactDescriptorResult; 071import org.eclipse.aether.resolution.ArtifactRequest; 072import org.eclipse.aether.resolution.ArtifactResolutionException; 073import org.eclipse.aether.resolution.ArtifactResult; 074import org.eclipse.aether.resolution.DependencyRequest; 075import org.eclipse.aether.resolution.DependencyResolutionException; 076import org.eclipse.aether.resolution.DependencyResult; 077import org.eclipse.aether.resolution.MetadataRequest; 078import org.eclipse.aether.resolution.MetadataResult; 079import org.eclipse.aether.resolution.VersionRangeRequest; 080import org.eclipse.aether.resolution.VersionRangeResolutionException; 081import org.eclipse.aether.resolution.VersionRangeResult; 082import org.eclipse.aether.resolution.VersionRequest; 083import org.eclipse.aether.resolution.VersionResolutionException; 084import org.eclipse.aether.resolution.VersionResult; 085import org.eclipse.aether.spi.synccontext.SyncContextFactory; 086import org.eclipse.aether.util.ConfigUtils; 087import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor; 088import org.eclipse.aether.util.graph.visitor.LevelOrderDependencyNodeConsumerVisitor; 089import org.eclipse.aether.util.graph.visitor.PostorderDependencyNodeConsumerVisitor; 090import org.eclipse.aether.util.graph.visitor.PreorderDependencyNodeConsumerVisitor; 091 092import static java.util.Objects.requireNonNull; 093 094/** 095 * 096 */ 097@Singleton 098@Named 099public class DefaultRepositorySystem implements RepositorySystem { 100 private final AtomicBoolean shutdown; 101 102 private final VersionResolver versionResolver; 103 104 private final VersionRangeResolver versionRangeResolver; 105 106 private final ArtifactResolver artifactResolver; 107 108 private final MetadataResolver metadataResolver; 109 110 private final ArtifactDescriptorReader artifactDescriptorReader; 111 112 private final DependencyCollector dependencyCollector; 113 114 private final Installer installer; 115 116 private final Deployer deployer; 117 118 private final LocalRepositoryProvider localRepositoryProvider; 119 120 private final SyncContextFactory syncContextFactory; 121 122 private final RemoteRepositoryManager remoteRepositoryManager; 123 124 private final RepositorySystemLifecycle repositorySystemLifecycle; 125 126 @SuppressWarnings("checkstyle:parameternumber") 127 @Inject 128 public DefaultRepositorySystem( 129 VersionResolver versionResolver, 130 VersionRangeResolver versionRangeResolver, 131 ArtifactResolver artifactResolver, 132 MetadataResolver metadataResolver, 133 ArtifactDescriptorReader artifactDescriptorReader, 134 DependencyCollector dependencyCollector, 135 Installer installer, 136 Deployer deployer, 137 LocalRepositoryProvider localRepositoryProvider, 138 SyncContextFactory syncContextFactory, 139 RemoteRepositoryManager remoteRepositoryManager, 140 RepositorySystemLifecycle repositorySystemLifecycle) { 141 this.shutdown = new AtomicBoolean(false); 142 this.versionResolver = requireNonNull(versionResolver, "version resolver cannot be null"); 143 this.versionRangeResolver = requireNonNull(versionRangeResolver, "version range resolver cannot be null"); 144 this.artifactResolver = requireNonNull(artifactResolver, "artifact resolver cannot be null"); 145 this.metadataResolver = requireNonNull(metadataResolver, "metadata resolver cannot be null"); 146 this.artifactDescriptorReader = 147 requireNonNull(artifactDescriptorReader, "artifact descriptor reader cannot be null"); 148 this.dependencyCollector = requireNonNull(dependencyCollector, "dependency collector cannot be null"); 149 this.installer = requireNonNull(installer, "installer cannot be null"); 150 this.deployer = requireNonNull(deployer, "deployer cannot be null"); 151 this.localRepositoryProvider = 152 requireNonNull(localRepositoryProvider, "local repository provider cannot be null"); 153 this.syncContextFactory = requireNonNull(syncContextFactory, "sync context factory cannot be null"); 154 this.remoteRepositoryManager = 155 requireNonNull(remoteRepositoryManager, "remote repository provider cannot be null"); 156 this.repositorySystemLifecycle = 157 requireNonNull(repositorySystemLifecycle, "repository system lifecycle cannot be null"); 158 } 159 160 @Override 161 public VersionResult resolveVersion(RepositorySystemSession session, VersionRequest request) 162 throws VersionResolutionException { 163 validateSession(session); 164 requireNonNull(request, "request cannot be null"); 165 166 return versionResolver.resolveVersion(session, request); 167 } 168 169 @Override 170 public VersionRangeResult resolveVersionRange(RepositorySystemSession session, VersionRangeRequest request) 171 throws VersionRangeResolutionException { 172 validateSession(session); 173 requireNonNull(request, "request cannot be null"); 174 175 return versionRangeResolver.resolveVersionRange(session, request); 176 } 177 178 @Override 179 public ArtifactDescriptorResult readArtifactDescriptor( 180 RepositorySystemSession session, ArtifactDescriptorRequest request) throws ArtifactDescriptorException { 181 validateSession(session); 182 requireNonNull(request, "request cannot be null"); 183 184 return artifactDescriptorReader.readArtifactDescriptor(session, request); 185 } 186 187 @Override 188 public ArtifactResult resolveArtifact(RepositorySystemSession session, ArtifactRequest request) 189 throws ArtifactResolutionException { 190 validateSession(session); 191 requireNonNull(request, "request cannot be null"); 192 193 return artifactResolver.resolveArtifact(session, request); 194 } 195 196 @Override 197 public List<ArtifactResult> resolveArtifacts( 198 RepositorySystemSession session, Collection<? extends ArtifactRequest> requests) 199 throws ArtifactResolutionException { 200 validateSession(session); 201 requireNonNull(requests, "requests cannot be null"); 202 203 return artifactResolver.resolveArtifacts(session, requests); 204 } 205 206 @Override 207 public List<MetadataResult> resolveMetadata( 208 RepositorySystemSession session, Collection<? extends MetadataRequest> requests) { 209 validateSession(session); 210 requireNonNull(requests, "requests cannot be null"); 211 212 return metadataResolver.resolveMetadata(session, requests); 213 } 214 215 @Override 216 public CollectResult collectDependencies(RepositorySystemSession session, CollectRequest request) 217 throws DependencyCollectionException { 218 validateSession(session); 219 requireNonNull(request, "request cannot be null"); 220 221 return dependencyCollector.collectDependencies(session, request); 222 } 223 224 @Override 225 public DependencyResult resolveDependencies(RepositorySystemSession session, DependencyRequest request) 226 throws DependencyResolutionException { 227 validateSession(session); 228 requireNonNull(request, "request cannot be null"); 229 230 RequestTrace trace = RequestTrace.newChild(request.getTrace(), request); 231 232 DependencyResult result = new DependencyResult(request); 233 234 DependencyCollectionException dce = null; 235 ArtifactResolutionException are = null; 236 237 if (request.getRoot() != null) { 238 result.setRoot(request.getRoot()); 239 } else if (request.getCollectRequest() != null) { 240 CollectResult collectResult; 241 try { 242 request.getCollectRequest().setTrace(trace); 243 collectResult = dependencyCollector.collectDependencies(session, request.getCollectRequest()); 244 } catch (DependencyCollectionException e) { 245 dce = e; 246 collectResult = e.getResult(); 247 } 248 result.setRoot(collectResult.getRoot()); 249 result.setCycles(collectResult.getCycles()); 250 result.setCollectExceptions(collectResult.getExceptions()); 251 } else { 252 throw new NullPointerException("dependency node and collect request cannot be null"); 253 } 254 255 final ArrayList<DependencyNode> dependencyNodes = new ArrayList<>(); 256 DependencyVisitor builder = getDependencyVisitor(session, dependencyNodes::add); 257 DependencyFilter filter = request.getFilter(); 258 DependencyVisitor visitor = (filter != null) ? new FilteringDependencyVisitor(builder, filter) : builder; 259 if (result.getRoot() != null) { 260 result.getRoot().accept(visitor); 261 } 262 263 final List<ArtifactRequest> requests = dependencyNodes.stream() 264 .map(n -> { 265 if (n.getDependency() != null) { 266 ArtifactRequest artifactRequest = new ArtifactRequest(n); 267 artifactRequest.setTrace(trace); 268 return artifactRequest; 269 } else { 270 return null; 271 } 272 }) 273 .filter(Objects::nonNull) 274 .collect(Collectors.toList()); 275 List<ArtifactResult> results; 276 try { 277 results = artifactResolver.resolveArtifacts(session, requests); 278 } catch (ArtifactResolutionException e) { 279 are = e; 280 results = e.getResults(); 281 } 282 result.setDependencyNodeResults(dependencyNodes); 283 result.setArtifactResults(results); 284 285 updateNodesWithResolvedArtifacts(results); 286 287 if (dce != null) { 288 throw new DependencyResolutionException(result, dce); 289 } else if (are != null) { 290 throw new DependencyResolutionException(result, are); 291 } 292 293 return result; 294 } 295 296 @Override 297 public List<DependencyNode> flattenDependencyNodes(RepositorySystemSession session, DependencyNode root) { 298 validateSession(session); 299 requireNonNull(root, "root cannot be null"); 300 301 final ArrayList<DependencyNode> dependencyNodes = new ArrayList<>(); 302 root.accept(getDependencyVisitor(session, dependencyNodes::add)); 303 return dependencyNodes; 304 } 305 306 private DependencyVisitor getDependencyVisitor( 307 RepositorySystemSession session, Consumer<DependencyNode> nodeConsumer) { 308 String strategy = ConfigUtils.getString( 309 session, 310 ConfigurationProperties.DEFAULT_REPOSITORY_SYSTEM_RESOLVER_DEPENDENCIES_VISITOR, 311 ConfigurationProperties.REPOSITORY_SYSTEM_RESOLVER_DEPENDENCIES_VISITOR); 312 switch (strategy) { 313 case PreorderDependencyNodeConsumerVisitor.NAME: 314 return new PreorderDependencyNodeConsumerVisitor(nodeConsumer); 315 case PostorderDependencyNodeConsumerVisitor.NAME: 316 return new PostorderDependencyNodeConsumerVisitor(nodeConsumer); 317 case LevelOrderDependencyNodeConsumerVisitor.NAME: 318 return new LevelOrderDependencyNodeConsumerVisitor(nodeConsumer); 319 default: 320 throw new IllegalArgumentException("Invalid dependency visitor strategy: " + strategy); 321 } 322 } 323 324 private void updateNodesWithResolvedArtifacts(List<ArtifactResult> results) { 325 for (ArtifactResult result : results) { 326 Artifact artifact = result.getArtifact(); 327 if (artifact != null) { 328 result.getRequest().getDependencyNode().setArtifact(artifact); 329 } 330 } 331 } 332 333 @Override 334 public InstallResult install(RepositorySystemSession session, InstallRequest request) throws InstallationException { 335 validateSession(session); 336 requireNonNull(request, "request cannot be null"); 337 338 return installer.install(session, request); 339 } 340 341 @Override 342 public DeployResult deploy(RepositorySystemSession session, DeployRequest request) throws DeploymentException { 343 validateSession(session); 344 requireNonNull(request, "request cannot be null"); 345 346 return deployer.deploy(session, request); 347 } 348 349 @Override 350 public LocalRepositoryManager newLocalRepositoryManager( 351 RepositorySystemSession session, LocalRepository localRepository) { 352 requireNonNull(session, "session cannot be null"); 353 requireNonNull(localRepository, "localRepository cannot be null"); 354 355 try { 356 return localRepositoryProvider.newLocalRepositoryManager(session, localRepository); 357 } catch (NoLocalRepositoryManagerException e) { 358 throw new IllegalArgumentException(e.getMessage(), e); 359 } 360 } 361 362 @Override 363 public SyncContext newSyncContext(RepositorySystemSession session, boolean shared) { 364 validateSession(session); 365 return syncContextFactory.newInstance(session, shared); 366 } 367 368 @Override 369 public List<RemoteRepository> newResolutionRepositories( 370 RepositorySystemSession session, List<RemoteRepository> repositories) { 371 validateSession(session); 372 validateRepositories(repositories); 373 374 repositories = remoteRepositoryManager.aggregateRepositories(session, new ArrayList<>(), repositories, true); 375 return repositories; 376 } 377 378 @Override 379 public RemoteRepository newDeploymentRepository(RepositorySystemSession session, RemoteRepository repository) { 380 validateSession(session); 381 requireNonNull(repository, "repository cannot be null"); 382 383 RemoteRepository.Builder builder = new RemoteRepository.Builder(repository); 384 Authentication auth = session.getAuthenticationSelector().getAuthentication(repository); 385 builder.setAuthentication(auth); 386 Proxy proxy = session.getProxySelector().getProxy(repository); 387 builder.setProxy(proxy); 388 return builder.build(); 389 } 390 391 @Override 392 public void addOnSystemEndedHandler(Runnable handler) { 393 repositorySystemLifecycle.addOnSystemEndedHandler(handler); 394 } 395 396 @Override 397 public void shutdown() { 398 if (shutdown.compareAndSet(false, true)) { 399 repositorySystemLifecycle.systemEnded(); 400 } 401 } 402 403 private void validateSession(RepositorySystemSession session) { 404 requireNonNull(session, "repository system session cannot be null"); 405 invalidSession(session.getLocalRepositoryManager(), "local repository manager"); 406 invalidSession(session.getSystemProperties(), "system properties"); 407 invalidSession(session.getUserProperties(), "user properties"); 408 invalidSession(session.getConfigProperties(), "config properties"); 409 invalidSession(session.getMirrorSelector(), "mirror selector"); 410 invalidSession(session.getProxySelector(), "proxy selector"); 411 invalidSession(session.getAuthenticationSelector(), "authentication selector"); 412 invalidSession(session.getArtifactTypeRegistry(), "artifact type registry"); 413 invalidSession(session.getData(), "data"); 414 if (shutdown.get()) { 415 throw new IllegalStateException("repository system is already shut down"); 416 } 417 } 418 419 private void validateRepositories(List<RemoteRepository> repositories) { 420 requireNonNull(repositories, "repositories cannot be null"); 421 for (RemoteRepository repository : repositories) { 422 requireNonNull(repository, "repository cannot be null"); 423 } 424 } 425 426 private void invalidSession(Object obj, String name) { 427 requireNonNull(obj, "repository system session's " + name + " cannot be null"); 428 } 429}