1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.install;
20
21 import java.io.File;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.function.Predicate;
25 import java.util.stream.Collectors;
26
27 import org.apache.maven.RepositoryUtils;
28 import org.apache.maven.execution.MavenSession;
29 import org.apache.maven.model.Plugin;
30 import org.apache.maven.model.PluginExecution;
31 import org.apache.maven.plugin.AbstractMojo;
32 import org.apache.maven.plugin.MojoExecutionException;
33 import org.apache.maven.plugin.descriptor.PluginDescriptor;
34 import org.apache.maven.plugins.annotations.Component;
35 import org.apache.maven.plugins.annotations.LifecyclePhase;
36 import org.apache.maven.plugins.annotations.Mojo;
37 import org.apache.maven.plugins.annotations.Parameter;
38 import org.apache.maven.project.MavenProject;
39 import org.apache.maven.project.artifact.ProjectArtifact;
40 import org.eclipse.aether.RepositorySystem;
41 import org.eclipse.aether.artifact.Artifact;
42 import org.eclipse.aether.installation.InstallRequest;
43 import org.eclipse.aether.installation.InstallationException;
44 import org.eclipse.aether.util.artifact.ArtifactIdUtils;
45
46
47
48
49
50
51
52 @Mojo(name = "install", defaultPhase = LifecyclePhase.INSTALL, threadSafe = true)
53 public class InstallMojo extends AbstractMojo {
54 @Component
55 private RepositorySystem repositorySystem;
56
57 @Parameter(defaultValue = "${session}", required = true, readonly = true)
58 private MavenSession session;
59
60 @Parameter(defaultValue = "${project}", readonly = true, required = true)
61 private MavenProject project;
62
63 @Parameter(defaultValue = "${plugin}", required = true, readonly = true)
64 private PluginDescriptor pluginDescriptor;
65
66
67
68
69
70
71
72
73 @Parameter(defaultValue = "false", property = "installAtEnd")
74 private boolean installAtEnd;
75
76
77
78
79
80
81
82 @Parameter(property = "maven.install.skip", defaultValue = "false")
83 private boolean skip;
84
85
86
87
88
89
90
91
92
93
94 @Parameter(defaultValue = "false", property = "allowIncompleteProjects")
95 private boolean allowIncompleteProjects;
96
97 private enum State {
98 SKIPPED,
99 INSTALLED,
100 TO_BE_INSTALLED
101 }
102
103 private static final String INSTALL_PROCESSED_MARKER = InstallMojo.class.getName() + ".processed";
104
105 private void putState(State state) {
106 getPluginContext().put(INSTALL_PROCESSED_MARKER, state.name());
107 }
108
109 private State getState(MavenProject project) {
110 Map<String, Object> pluginContext = session.getPluginContext(pluginDescriptor, project);
111 return State.valueOf((String) pluginContext.get(INSTALL_PROCESSED_MARKER));
112 }
113
114 private boolean hasState(MavenProject project) {
115 Map<String, Object> pluginContext = session.getPluginContext(pluginDescriptor, project);
116 return pluginContext.containsKey(INSTALL_PROCESSED_MARKER);
117 }
118
119 @Override
120 public void execute() throws MojoExecutionException {
121 if (skip) {
122 getLog().info("Skipping artifact installation");
123 putState(State.SKIPPED);
124 } else {
125 if (installAtEnd) {
126 getLog().info("Deferring install for " + project.getGroupId() + ":" + project.getArtifactId() + ":"
127 + project.getVersion() + " at end");
128 putState(State.TO_BE_INSTALLED);
129 } else {
130 InstallRequest request = new InstallRequest();
131 processProject(project, request);
132 installProject(request);
133 putState(State.INSTALLED);
134 }
135 }
136
137 List<MavenProject> allProjectsUsingPlugin = getAllProjectsUsingPlugin();
138
139 if (allProjectsMarked(allProjectsUsingPlugin)) {
140 InstallRequest request = new InstallRequest();
141 for (MavenProject reactorProject : allProjectsUsingPlugin) {
142 State state = getState(reactorProject);
143 if (state == State.TO_BE_INSTALLED) {
144 processProject(reactorProject, request);
145 }
146 }
147 installProject(request);
148 }
149 }
150
151 private boolean allProjectsMarked(List<MavenProject> allProjectsUsingPlugin) {
152 return allProjectsUsingPlugin.stream().allMatch(this::hasState);
153 }
154
155 private final Predicate<MavenProject> hasMavenInstallPluginExecution =
156 rp -> hasExecution(rp.getPlugin("org.apache.maven.plugins:maven-install-plugin"));
157
158 private List<MavenProject> getAllProjectsUsingPlugin() {
159 return session.getProjects().stream()
160 .filter(hasMavenInstallPluginExecution)
161 .collect(Collectors.toList());
162 }
163
164 private final Predicate<PluginExecution> havingGoals = pe -> !pe.getGoals().isEmpty();
165 private final Predicate<PluginExecution> nonePhase = pe -> !"none".equalsIgnoreCase(pe.getPhase());
166
167 private boolean hasExecution(Plugin plugin) {
168 if (plugin == null) {
169 return false;
170 }
171
172 return plugin.getExecutions().stream().filter(havingGoals).anyMatch(nonePhase);
173 }
174
175 private void installProject(InstallRequest request) throws MojoExecutionException {
176 try {
177 repositorySystem.install(session.getRepositorySession(), request);
178 } catch (InstallationException e) {
179 throw new MojoExecutionException(e.getMessage(), e);
180 }
181 }
182
183
184
185
186
187
188 private void processProject(MavenProject project, InstallRequest request) throws MojoExecutionException {
189
190 Artifact pomArtifact = RepositoryUtils.toArtifact(new ProjectArtifact(project));
191
192 Artifact projectArtifact = RepositoryUtils.toArtifact(project.getArtifact());
193
194
195
196
197
198
199
200 if (ArtifactIdUtils.equalsId(pomArtifact, projectArtifact)) {
201 if (isFile(projectArtifact.getFile())) {
202 pomArtifact = projectArtifact;
203 }
204 projectArtifact = null;
205 }
206
207 if (isFile(pomArtifact.getFile())) {
208 request.addArtifact(pomArtifact);
209 } else {
210 throw new MojoExecutionException(
211 "The POM for project " + project.getArtifactId() + " could not be attached");
212 }
213
214
215 boolean isIncomplete = projectArtifact != null && !isFile(projectArtifact.getFile());
216 if (projectArtifact != null) {
217 if (!isIncomplete) {
218 request.addArtifact(projectArtifact);
219 } else if (!project.getAttachedArtifacts().isEmpty()) {
220 if (allowIncompleteProjects) {
221 getLog().warn("");
222 getLog().warn("The packaging plugin for project " + project.getArtifactId() + " did not assign");
223 getLog().warn("a main file to the project but it has attachments. Change packaging to 'pom'.");
224 getLog().warn("");
225 getLog().warn("Incomplete projects like this will fail in future Maven versions!");
226 getLog().warn("");
227 } else {
228 throw new MojoExecutionException("The packaging plugin for project " + project.getArtifactId()
229 + " did not assign a main file to the project but it has attachments. Change packaging"
230 + " to 'pom'.");
231 }
232 } else {
233 throw new MojoExecutionException("The packaging plugin for project " + project.getArtifactId()
234 + " did not assign a file to the build artifact");
235 }
236 }
237
238 for (org.apache.maven.artifact.Artifact attached : project.getAttachedArtifacts()) {
239 getLog().debug("Attaching for install: " + attached.getId());
240 request.addArtifact(RepositoryUtils.toArtifact(attached));
241 }
242 }
243
244 private boolean isFile(File file) {
245 return file != null && file.isFile();
246 }
247 }