1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.invoker;
20
21 import java.io.File;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.LinkedHashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Optional;
29 import java.util.stream.Collectors;
30
31 import org.apache.maven.RepositoryUtils;
32 import org.apache.maven.execution.MavenSession;
33 import org.apache.maven.model.DependencyManagement;
34 import org.apache.maven.model.Model;
35 import org.apache.maven.model.Parent;
36 import org.apache.maven.plugin.AbstractMojo;
37 import org.apache.maven.plugin.MojoExecutionException;
38 import org.apache.maven.plugins.annotations.Component;
39 import org.apache.maven.plugins.annotations.LifecyclePhase;
40 import org.apache.maven.plugins.annotations.Mojo;
41 import org.apache.maven.plugins.annotations.Parameter;
42 import org.apache.maven.plugins.annotations.ResolutionScope;
43 import org.apache.maven.project.MavenProject;
44 import org.apache.maven.project.artifact.ProjectArtifact;
45 import org.eclipse.aether.DefaultRepositoryCache;
46 import org.eclipse.aether.DefaultRepositorySystemSession;
47 import org.eclipse.aether.RepositorySystem;
48 import org.eclipse.aether.RepositorySystemSession;
49 import org.eclipse.aether.artifact.Artifact;
50 import org.eclipse.aether.artifact.ArtifactType;
51 import org.eclipse.aether.artifact.ArtifactTypeRegistry;
52 import org.eclipse.aether.artifact.DefaultArtifact;
53 import org.eclipse.aether.collection.CollectRequest;
54 import org.eclipse.aether.graph.Dependency;
55 import org.eclipse.aether.graph.DependencyFilter;
56 import org.eclipse.aether.installation.InstallRequest;
57 import org.eclipse.aether.installation.InstallationException;
58 import org.eclipse.aether.repository.LocalRepository;
59 import org.eclipse.aether.repository.LocalRepositoryManager;
60 import org.eclipse.aether.repository.RemoteRepository;
61 import org.eclipse.aether.resolution.ArtifactDescriptorException;
62 import org.eclipse.aether.resolution.ArtifactRequest;
63 import org.eclipse.aether.resolution.ArtifactResolutionException;
64 import org.eclipse.aether.resolution.ArtifactResult;
65 import org.eclipse.aether.resolution.DependencyRequest;
66 import org.eclipse.aether.resolution.DependencyResolutionException;
67 import org.eclipse.aether.resolution.DependencyResult;
68 import org.eclipse.aether.util.artifact.JavaScopes;
69 import org.eclipse.aether.util.artifact.SubArtifact;
70 import org.eclipse.aether.util.filter.DependencyFilterUtils;
71
72
73
74
75
76
77
78
79
80
81 @Mojo(
82 name = "install",
83 defaultPhase = LifecyclePhase.PRE_INTEGRATION_TEST,
84 requiresDependencyResolution = ResolutionScope.TEST,
85 threadSafe = true)
86 public class InstallMojo extends AbstractMojo {
87
88
89
90 @Component
91 private RepositorySystem repositorySystem;
92
93 @Parameter(defaultValue = "${session}", readonly = true, required = true)
94 private MavenSession session;
95
96 @Parameter(defaultValue = "${project}", readonly = true, required = true)
97 private MavenProject project;
98
99
100
101
102
103
104
105 @Parameter(
106 property = "invoker.localRepositoryPath",
107 defaultValue = "${session.localRepository.basedir}",
108 required = true)
109 private File localRepositoryPath;
110
111
112
113
114
115
116
117 @Parameter(property = "invoker.skip", defaultValue = "false")
118 private boolean skipInstallation;
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 @Parameter
142 private String[] extraArtifacts;
143
144
145
146
147
148
149 @Parameter(property = "invoker.install.scope", defaultValue = "runtime")
150 private String scope;
151
152
153
154
155
156
157 public void execute() throws MojoExecutionException {
158 if (skipInstallation) {
159 getLog().info("Skipping artifact installation per configuration.");
160 return;
161 }
162
163 Collection<Artifact> resolvedArtifacts = new ArrayList<>();
164
165 try {
166
167 resolveProjectArtifacts(resolvedArtifacts);
168 resolveProjectPoms(project, resolvedArtifacts);
169 resolveProjectDependencies(resolvedArtifacts);
170 resolveExtraArtifacts(resolvedArtifacts);
171 installArtifacts(resolvedArtifacts);
172
173 } catch (DependencyResolutionException
174 | InstallationException
175 | ArtifactDescriptorException
176 | ArtifactResolutionException e) {
177 throw new MojoExecutionException(e.getMessage(), e);
178 }
179 }
180
181 private void resolveProjectArtifacts(Collection<Artifact> resolvedArtifacts) {
182
183
184 if (project.getArtifact() != null && project.getArtifact().getFile() != null) {
185 resolvedArtifacts.add(RepositoryUtils.toArtifact(project.getArtifact()));
186 }
187
188 resolvedArtifacts.addAll(project.getAttachedArtifacts().stream()
189 .map(RepositoryUtils::toArtifact)
190 .collect(Collectors.toList()));
191 }
192
193 private void resolveProjectPoms(MavenProject project, Collection<Artifact> resolvedArtifacts)
194 throws ArtifactResolutionException {
195
196 if (project == null) {
197 return;
198 }
199
200 Artifact projectPom = RepositoryUtils.toArtifact(new ProjectArtifact(project));
201 if (projectPom.getFile() != null) {
202 resolvedArtifacts.add(projectPom);
203 } else {
204 Artifact artifact = resolveArtifact(projectPom, project.getRemoteProjectRepositories());
205 resolvedArtifacts.add(artifact);
206 }
207 resolveProjectPoms(project.getParent(), resolvedArtifacts);
208 }
209
210 private void resolveProjectDependencies(Collection<Artifact> resolvedArtifacts)
211 throws ArtifactResolutionException, MojoExecutionException, DependencyResolutionException {
212
213 DependencyFilter classpathFilter = DependencyFilterUtils.classpathFilter(scope);
214
215 ArtifactTypeRegistry artifactTypeRegistry =
216 session.getRepositorySession().getArtifactTypeRegistry();
217
218 List<Dependency> managedDependencies = Optional.ofNullable(project.getDependencyManagement())
219 .map(DependencyManagement::getDependencies)
220 .orElseGet(Collections::emptyList)
221 .stream()
222 .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry))
223 .collect(Collectors.toList());
224
225 List<Dependency> dependencies = project.getDependencies().stream()
226 .map(d -> RepositoryUtils.toDependency(d, artifactTypeRegistry))
227 .collect(Collectors.toList());
228
229 CollectRequest collectRequest = new CollectRequest();
230 collectRequest.setRootArtifact(RepositoryUtils.toArtifact(project.getArtifact()));
231 collectRequest.setDependencies(dependencies);
232 collectRequest.setManagedDependencies(managedDependencies);
233
234 collectRequest.setRepositories(project.getRemoteProjectRepositories());
235
236 DependencyRequest request = new DependencyRequest(collectRequest, classpathFilter);
237
238 DependencyResult dependencyResult =
239 repositorySystem.resolveDependencies(session.getRepositorySession(), request);
240
241 List<Artifact> artifacts = dependencyResult.getArtifactResults().stream()
242 .map(ArtifactResult::getArtifact)
243 .collect(Collectors.toList());
244
245 resolvedArtifacts.addAll(artifacts);
246 resolvePomsForArtifacts(artifacts, resolvedArtifacts, collectRequest.getRepositories());
247 }
248
249
250
251
252
253
254 private void resolveExtraArtifacts(Collection<Artifact> resolvedArtifacts)
255 throws MojoExecutionException, DependencyResolutionException, ArtifactDescriptorException,
256 ArtifactResolutionException {
257
258 if (extraArtifacts == null) {
259 return;
260 }
261
262 DependencyFilter classpathFilter = DependencyFilterUtils.classpathFilter(JavaScopes.RUNTIME);
263
264 for (String extraArtifact : extraArtifacts) {
265 String[] gav = extraArtifact.split(":");
266 if (gav.length < 3 || gav.length > 5) {
267 throw new MojoExecutionException("Invalid artifact " + extraArtifact);
268 }
269
270 String groupId = gav[0];
271 String artifactId = gav[1];
272 String version = gav[2];
273
274 String type = "jar";
275 if (gav.length > 3) {
276 type = gav[3];
277 }
278
279 String classifier = null;
280 if (gav.length == 5) {
281 classifier = gav[4];
282 }
283
284 ArtifactType artifactType =
285 session.getRepositorySession().getArtifactTypeRegistry().get(type);
286
287 List<RemoteRepository> remoteRepositories =
288 artifactType != null && "maven-plugin".equals(artifactType.getId())
289 ? project.getRemotePluginRepositories()
290 : project.getRemoteProjectRepositories();
291
292 Artifact artifact = new DefaultArtifact(groupId, artifactId, classifier, null, version, artifactType);
293
294 resolvePomsForArtifacts(Collections.singletonList(artifact), resolvedArtifacts, remoteRepositories);
295
296 CollectRequest collectRequest = new CollectRequest();
297 Dependency root = new Dependency(artifact, JavaScopes.COMPILE);
298 collectRequest.setRoot(root);
299 collectRequest.setRepositories(remoteRepositories);
300
301 DependencyRequest request = new DependencyRequest(collectRequest, classpathFilter);
302 DependencyResult dependencyResult =
303 repositorySystem.resolveDependencies(session.getRepositorySession(), request);
304
305 List<Artifact> artifacts = dependencyResult.getArtifactResults().stream()
306 .map(ArtifactResult::getArtifact)
307 .collect(Collectors.toList());
308
309 resolvedArtifacts.addAll(artifacts);
310 resolvePomsForArtifacts(artifacts, resolvedArtifacts, collectRequest.getRepositories());
311 }
312 }
313
314 private void resolvePomsForArtifacts(
315 List<Artifact> artifacts, Collection<Artifact> resolvedArtifacts, List<RemoteRepository> remoteRepositories)
316 throws ArtifactResolutionException, MojoExecutionException {
317
318 for (Artifact a : artifacts) {
319 Artifact artifactResult = resolveArtifact(new SubArtifact(a, "", "pom"), remoteRepositories);
320 resolvePomWithParents(artifactResult, resolvedArtifacts, remoteRepositories);
321 }
322 }
323
324 private void resolvePomWithParents(
325 Artifact artifact, Collection<Artifact> resolvedArtifacts, List<RemoteRepository> remoteRepositories)
326 throws MojoExecutionException, ArtifactResolutionException {
327
328 if (resolvedArtifacts.contains(artifact)) {
329 return;
330 }
331
332 Model model = PomUtils.loadPom(artifact.getFile());
333 Parent parent = model.getParent();
334 if (parent != null) {
335 DefaultArtifact pom =
336 new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), "", "pom", parent.getVersion());
337 Artifact resolvedPom = resolveArtifact(pom, remoteRepositories);
338 resolvePomWithParents(resolvedPom, resolvedArtifacts, remoteRepositories);
339 }
340
341 resolvedArtifacts.add(artifact);
342 }
343
344 private Artifact resolveArtifact(Artifact artifact, List<RemoteRepository> remoteRepositories)
345 throws ArtifactResolutionException {
346
347 ArtifactRequest request = new ArtifactRequest();
348 request.setArtifact(artifact);
349 request.setRepositories(remoteRepositories);
350 ArtifactResult artifactResult = repositorySystem.resolveArtifact(session.getRepositorySession(), request);
351 return artifactResult.getArtifact();
352 }
353
354
355
356
357 private void installArtifacts(Collection<Artifact> resolvedArtifacts) throws InstallationException {
358
359
360
361
362
363 Map<String, List<Artifact>> collect = resolvedArtifacts.stream()
364 .collect(Collectors.groupingBy(
365 a -> String.format("%s:%s:%s", a.getGroupId(), a.getArtifactId(), a.getVersion()),
366 LinkedHashMap::new,
367 Collectors.toList()));
368
369 RepositorySystemSession systemSessionForLocalRepo = createSystemSessionForLocalRepo();
370
371 for (List<Artifact> artifacts : collect.values()) {
372 InstallRequest request = new InstallRequest();
373 request.setArtifacts(artifacts);
374 repositorySystem.install(systemSessionForLocalRepo, request);
375 }
376 }
377
378
379
380
381 private RepositorySystemSession createSystemSessionForLocalRepo() {
382 RepositorySystemSession repositorySystemSession = session.getRepositorySession();
383 if (localRepositoryPath != null) {
384
385 DefaultRepositorySystemSession newSession =
386 new DefaultRepositorySystemSession(session.getRepositorySession());
387
388 newSession.setCache(new DefaultRepositoryCache());
389
390 String contentType = newSession.getLocalRepository().getContentType();
391 if ("enhanced".equals(contentType)) {
392 contentType = "default";
393 }
394 LocalRepositoryManager localRepositoryManager = repositorySystem.newLocalRepositoryManager(
395 newSession, new LocalRepository(localRepositoryPath, contentType));
396
397 newSession.setLocalRepositoryManager(localRepositoryManager);
398 repositorySystemSession = newSession;
399 getLog().debug("localRepoPath: "
400 + localRepositoryManager.getRepository().getBasedir());
401 }
402
403 return repositorySystemSession;
404 }
405 }