View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.internal.impl;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.io.IOException;
25  import java.nio.file.Path;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Objects;
29  import java.util.Set;
30  import java.util.function.Predicate;
31  import java.util.stream.Collectors;
32  
33  import org.apache.maven.api.*;
34  import org.apache.maven.api.Artifact;
35  import org.apache.maven.api.ArtifactCoordinate;
36  import org.apache.maven.api.Dependency;
37  import org.apache.maven.api.Node;
38  import org.apache.maven.api.PathType;
39  import org.apache.maven.api.Session;
40  import org.apache.maven.api.services.*;
41  import org.eclipse.aether.graph.DependencyFilter;
42  import org.eclipse.aether.graph.DependencyNode;
43  
44  import static org.apache.maven.internal.impl.Utils.cast;
45  import static org.apache.maven.internal.impl.Utils.map;
46  import static org.apache.maven.internal.impl.Utils.nonNull;
47  
48  @Named
49  @Singleton
50  public class DefaultDependencyResolver implements DependencyResolver {
51  
52      @Override
53      public List<Node> flatten(Session s, Node node, PathScope scope) throws DependencyResolverException {
54          InternalSession session = InternalSession.from(s);
55          DependencyNode root = cast(AbstractNode.class, node, "node").getDependencyNode();
56          List<DependencyNode> dependencies = session.getRepositorySystem()
57                  .flattenDependencyNodes(session.getSession(), root, getScopeDependencyFilter(scope));
58          dependencies.remove(root);
59          return map(dependencies, session::getNode);
60      }
61  
62      private static DependencyFilter getScopeDependencyFilter(PathScope scope) {
63          Set<String> scopes =
64                  scope.dependencyScopes().stream().map(DependencyScope::id).collect(Collectors.toSet());
65          return (n, p) -> {
66              org.eclipse.aether.graph.Dependency d = n.getDependency();
67              return d == null || scopes.contains(d.getScope());
68          };
69      }
70  
71      /**
72       * Collects, flattens and resolves the dependencies.
73       *
74       * @param request the request to resolve
75       * @return the result of the resolution
76       */
77      @Override
78      public DependencyResolverResult resolve(DependencyResolverRequest request)
79              throws DependencyCollectorException, DependencyResolverException, ArtifactResolverException {
80          InternalSession session =
81                  InternalSession.from(nonNull(request, "request").getSession());
82          Predicate<PathType> filter = request.getPathTypeFilter();
83          PathModularizationCache cache = new PathModularizationCache(); // TODO: should be project-wide cache.
84          DependencyCollectorResult collectorResult =
85                  session.getService(DependencyCollector.class).collect(request);
86          List<Node> nodes = flatten(session, collectorResult.getRoot(), request.getPathScope());
87          List<ArtifactCoordinate> coordinates = nodes.stream()
88                  .map(Node::getDependency)
89                  .filter(Objects::nonNull)
90                  .map(Artifact::toCoordinate)
91                  .collect(Collectors.toList());
92          Map<Artifact, Path> artifacts = session.resolveArtifacts(coordinates);
93          DefaultDependencyResolverResult result = new DefaultDependencyResolverResult(
94                  cache, collectorResult.getExceptions(), collectorResult.getRoot(), nodes.size());
95          for (Node node : nodes) {
96              Dependency d = node.getDependency();
97              Path path = (d != null) ? artifacts.get(d) : null;
98              try {
99                  result.addDependency(node, d, filter, path);
100             } catch (IOException e) {
101                 throw cannotReadModuleInfo(path, e);
102             }
103         }
104         return result;
105     }
106 
107     private static DependencyResolverException cannotReadModuleInfo(final Path path, final IOException cause) {
108         return new DependencyResolverException("Cannot read module information of " + path, cause);
109     }
110 }