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.Inject;
22  import javax.inject.Named;
23  
24  import java.nio.file.Path;
25  import java.nio.file.Paths;
26  import java.util.ArrayList;
27  import java.util.Collection;
28  import java.util.Collections;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Objects;
32  import java.util.Optional;
33  import java.util.Properties;
34  import java.util.stream.Collectors;
35  
36  import org.apache.maven.RepositoryUtils;
37  import org.apache.maven.api.ProducedArtifact;
38  import org.apache.maven.api.Project;
39  import org.apache.maven.api.ProjectScope;
40  import org.apache.maven.api.RemoteRepository;
41  import org.apache.maven.api.annotations.Nonnull;
42  import org.apache.maven.api.di.SessionScoped;
43  import org.apache.maven.api.model.Resource;
44  import org.apache.maven.api.services.ArtifactManager;
45  import org.apache.maven.api.services.ProjectManager;
46  import org.apache.maven.project.MavenProject;
47  import org.eclipse.sisu.Typed;
48  
49  import static java.util.stream.Collectors.toList;
50  import static org.apache.maven.internal.impl.Utils.map;
51  import static org.apache.maven.internal.impl.Utils.nonNull;
52  
53  @Named
54  @Typed
55  @SessionScoped
56  public class DefaultProjectManager implements ProjectManager {
57  
58      private final InternalMavenSession session;
59      private final ArtifactManager artifactManager;
60  
61      @Inject
62      public DefaultProjectManager(InternalMavenSession session, ArtifactManager artifactManager) {
63          this.session = session;
64          this.artifactManager = artifactManager;
65      }
66  
67      @Nonnull
68      @Override
69      public Optional<Path> getPath(Project project) {
70          Optional<ProducedArtifact> mainArtifact = project.getMainArtifact();
71          if (mainArtifact.isPresent()) {
72              return artifactManager.getPath(mainArtifact.get());
73          }
74          return Optional.empty();
75      }
76  
77      @Nonnull
78      @Override
79      public Collection<ProducedArtifact> getAttachedArtifacts(Project project) {
80          InternalMavenSession session = ((DefaultProject) project).getSession();
81          Collection<ProducedArtifact> attached = map(
82                  getMavenProject(project).getAttachedArtifacts(),
83                  a -> session.getArtifact(ProducedArtifact.class, RepositoryUtils.toArtifact(a)));
84          return Collections.unmodifiableCollection(attached);
85      }
86  
87      @Override
88      public Collection<ProducedArtifact> getAllArtifacts(Project project) {
89          ArrayList<ProducedArtifact> result = new ArrayList<>(2);
90          result.addAll(project.getArtifacts());
91          result.addAll(getAttachedArtifacts(project));
92          return Collections.unmodifiableCollection(result);
93      }
94  
95      @Override
96      public void attachArtifact(Project project, ProducedArtifact artifact, Path path) {
97          nonNull(project, "project");
98          nonNull(artifact, "artifact");
99          nonNull(path, "path");
100         if (artifact.getGroupId().isEmpty()
101                 || artifact.getArtifactId().isEmpty()
102                 || artifact.getBaseVersion().asString().isEmpty()) {
103             artifact = session.createProducedArtifact(
104                     artifact.getGroupId().isEmpty() ? project.getGroupId() : artifact.getGroupId(),
105                     artifact.getArtifactId().isEmpty() ? project.getArtifactId() : artifact.getArtifactId(),
106                     artifact.getBaseVersion().asString().isEmpty()
107                             ? session.parseVersion(project.getVersion()).asString()
108                             : artifact.getBaseVersion().asString(),
109                     artifact.getClassifier(),
110                     artifact.getExtension(),
111                     null);
112         }
113         if (!Objects.equals(project.getGroupId(), artifact.getGroupId())
114                 || !Objects.equals(project.getArtifactId(), artifact.getArtifactId())
115                 || !Objects.equals(
116                         project.getVersion(), artifact.getBaseVersion().asString())) {
117             throw new IllegalArgumentException(
118                     "The produced artifact must have the same groupId/artifactId/version than the project it is attached to. Expecting "
119                             + project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion()
120                             + " but received " + artifact.getGroupId() + ":" + artifact.getArtifactId() + ":"
121                             + artifact.getBaseVersion());
122         }
123         getMavenProject(project)
124                 .addAttachedArtifact(RepositoryUtils.toArtifact(
125                         ((DefaultProject) project).getSession().toArtifact(artifact)));
126         artifactManager.setPath(artifact, path);
127     }
128 
129     @Override
130     public List<Path> getCompileSourceRoots(Project project, ProjectScope scope) {
131         MavenProject prj = getMavenProject(nonNull(project, "project"));
132         List<String> roots;
133         if (nonNull(scope, "scope") == ProjectScope.MAIN) {
134             roots = prj.getCompileSourceRoots();
135         } else if (scope == ProjectScope.TEST) {
136             roots = prj.getTestCompileSourceRoots();
137         } else {
138             throw new IllegalArgumentException("Unsupported scope " + scope);
139         }
140         return roots.stream()
141                 .map(Paths::get)
142                 .collect(Collectors.collectingAndThen(toList(), Collections::unmodifiableList));
143     }
144 
145     @Override
146     public void addCompileSourceRoot(Project project, ProjectScope scope, Path sourceRoot) {
147         MavenProject prj = getMavenProject(nonNull(project, "project"));
148         String root = nonNull(sourceRoot, "sourceRoot").toAbsolutePath().toString();
149         if (nonNull(scope, "scope") == ProjectScope.MAIN) {
150             prj.addCompileSourceRoot(root);
151         } else if (scope == ProjectScope.TEST) {
152             prj.addTestCompileSourceRoot(root);
153         } else {
154             throw new IllegalArgumentException("Unsupported scope " + scope);
155         }
156     }
157 
158     @Override
159     public List<Resource> getResources(@Nonnull Project project, @Nonnull ProjectScope scope) {
160         Project prj = nonNull(project, "project");
161         if (nonNull(scope, "scope") == ProjectScope.MAIN) {
162             return prj.getBuild().getResources();
163         } else if (scope == ProjectScope.TEST) {
164             return prj.getBuild().getTestResources();
165         } else {
166             throw new IllegalArgumentException("Unsupported scope " + scope);
167         }
168     }
169 
170     @Override
171     public void addResource(@Nonnull Project project, @Nonnull ProjectScope scope, @Nonnull Resource resource) {
172         // TODO: we should not modify the underlying model here, but resources should be stored
173         // TODO: in a separate field in the project, however, that could break v3 plugins
174         MavenProject prj = getMavenProject(nonNull(project, "project"));
175         org.apache.maven.model.Resource res = new org.apache.maven.model.Resource(nonNull(resource, "resource"));
176         if (nonNull(scope, "scope") == ProjectScope.MAIN) {
177             prj.addResource(res);
178         } else if (scope == ProjectScope.TEST) {
179             prj.addTestResource(res);
180         } else {
181             throw new IllegalArgumentException("Unsupported scope " + scope);
182         }
183     }
184 
185     @Override
186     public List<RemoteRepository> getRemoteProjectRepositories(Project project) {
187         return Collections.unmodifiableList(new MappedList<>(
188                 ((DefaultProject) project).getProject().getRemoteProjectRepositories(), session::getRemoteRepository));
189     }
190 
191     @Override
192     public List<RemoteRepository> getRemotePluginRepositories(Project project) {
193         return Collections.unmodifiableList(new MappedList<>(
194                 ((DefaultProject) project).getProject().getRemotePluginRepositories(), session::getRemoteRepository));
195     }
196 
197     @Override
198     public void setProperty(Project project, String key, String value) {
199         Properties properties = getMavenProject(project).getProperties();
200         if (value == null) {
201             properties.remove(key);
202         } else {
203             properties.setProperty(key, value);
204         }
205     }
206 
207     @Override
208     public Map<String, String> getProperties(Project project) {
209         return Collections.unmodifiableMap(
210                 new PropertiesAsMap(((DefaultProject) project).getProject().getProperties()));
211     }
212 
213     @Override
214     public Optional<Project> getExecutionProject(Project project) {
215         // Session keep tracks of the Project per project id,
216         // so we cannot use session.getProject(p) for forked projects
217         // which are temporary clones
218         return Optional.ofNullable(getMavenProject(project).getExecutionProject())
219                 .map(p -> new DefaultProject(session, p));
220     }
221 
222     private MavenProject getMavenProject(Project project) {
223         return ((DefaultProject) project).getProject();
224     }
225 }