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.lifecycle.internal;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  
24  import java.io.File;
25  import java.util.Arrays;
26  import java.util.LinkedHashSet;
27  import java.util.List;
28  import java.util.Set;
29  
30  import org.apache.maven.artifact.Artifact;
31  import org.apache.maven.artifact.factory.ArtifactFactory;
32  import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
33  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
34  import org.apache.maven.artifact.resolver.filter.ExclusionArtifactFilter;
35  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
36  import org.apache.maven.artifact.versioning.VersionRange;
37  import org.apache.maven.model.Dependency;
38  import org.apache.maven.project.MavenProject;
39  import org.apache.maven.project.artifact.InvalidDependencyVersionException;
40  
41  /**
42   * Default component responsible for creation of MavenProject#dependencyArtifacts instances.
43   */
44  @SuppressWarnings("deprecation")
45  @Named
46  public class DefaultProjectArtifactFactory implements ProjectArtifactFactory {
47      private final ArtifactFactory artifactFactory;
48  
49      @Inject
50      public DefaultProjectArtifactFactory(ArtifactFactory artifactFactory) {
51          this.artifactFactory = artifactFactory;
52      }
53  
54      @Override
55      public Set<Artifact> createArtifacts(MavenProject project) throws InvalidDependencyVersionException {
56          return createArtifacts(artifactFactory, project.getDependencies(), null, null, project);
57      }
58  
59      public static Set<Artifact> createArtifacts(
60              ArtifactFactory artifactFactory,
61              List<Dependency> dependencies,
62              String inheritedScope,
63              ArtifactFilter dependencyFilter,
64              MavenProject project)
65              throws InvalidDependencyVersionException {
66          Set<Artifact> artifacts = new LinkedHashSet<>();
67  
68          for (Dependency d : dependencies) {
69              Artifact dependencyArtifact;
70              try {
71                  dependencyArtifact = createDependencyArtifact(artifactFactory, d, inheritedScope, dependencyFilter);
72              } catch (InvalidVersionSpecificationException e) {
73                  throw new InvalidDependencyVersionException(project.getId(), d, project.getFile(), e);
74              }
75  
76              if (dependencyArtifact != null) {
77                  artifacts.add(dependencyArtifact);
78              }
79          }
80  
81          return artifacts;
82      }
83  
84      private static Artifact createDependencyArtifact(
85              ArtifactFactory factory, Dependency dependency, String inheritedScope, ArtifactFilter inheritedFilter)
86              throws InvalidVersionSpecificationException {
87          String effectiveScope = getEffectiveScope(dependency.getScope(), inheritedScope);
88  
89          if (effectiveScope == null) {
90              return null;
91          }
92  
93          VersionRange versionRange = VersionRange.createFromVersionSpec(dependency.getVersion());
94  
95          Artifact dependencyArtifact = factory.createDependencyArtifact(
96                  dependency.getGroupId(),
97                  dependency.getArtifactId(),
98                  versionRange,
99                  dependency.getType(),
100                 dependency.getClassifier(),
101                 effectiveScope,
102                 dependency.isOptional());
103 
104         if (inheritedFilter != null && !inheritedFilter.include(dependencyArtifact)) {
105             return null;
106         }
107 
108         if (Artifact.SCOPE_SYSTEM.equals(effectiveScope)) {
109             dependencyArtifact.setFile(new File(dependency.getSystemPath()));
110         }
111 
112         dependencyArtifact.setDependencyFilter(createDependencyFilter(dependency, inheritedFilter));
113 
114         return dependencyArtifact;
115     }
116 
117     private static String getEffectiveScope(String originalScope, String inheritedScope) {
118         String effectiveScope = Artifact.SCOPE_RUNTIME;
119 
120         if (originalScope == null) {
121             originalScope = Artifact.SCOPE_COMPILE;
122         }
123 
124         if (inheritedScope == null) {
125             // direct dependency retains its scope
126             effectiveScope = originalScope;
127         } else if (Artifact.SCOPE_TEST.equals(originalScope) || Artifact.SCOPE_PROVIDED.equals(originalScope)) {
128             // test and provided are not transitive, so exclude them
129             effectiveScope = null;
130         } else if (Artifact.SCOPE_SYSTEM.equals(originalScope)) {
131             // system scope come through unchanged...
132             effectiveScope = Artifact.SCOPE_SYSTEM;
133         } else if (Artifact.SCOPE_COMPILE.equals(originalScope) && Artifact.SCOPE_COMPILE.equals(inheritedScope)) {
134             // added to retain compile scope. Remove if you want compile inherited as runtime
135             effectiveScope = Artifact.SCOPE_COMPILE;
136         } else if (Artifact.SCOPE_TEST.equals(inheritedScope)) {
137             effectiveScope = Artifact.SCOPE_TEST;
138         } else if (Artifact.SCOPE_PROVIDED.equals(inheritedScope)) {
139             effectiveScope = Artifact.SCOPE_PROVIDED;
140         }
141 
142         return effectiveScope;
143     }
144 
145     private static ArtifactFilter createDependencyFilter(Dependency dependency, ArtifactFilter inheritedFilter) {
146         ArtifactFilter effectiveFilter = inheritedFilter;
147 
148         if (!dependency.getExclusions().isEmpty()) {
149             effectiveFilter = new ExclusionArtifactFilter(dependency.getExclusions());
150 
151             if (inheritedFilter != null) {
152                 effectiveFilter = new AndArtifactFilter(Arrays.asList(inheritedFilter, effectiveFilter));
153             }
154         }
155 
156         return effectiveFilter;
157     }
158 }