1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugins.dependency.resolvers;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.util.ArrayList;
26 import java.util.Collections;
27 import java.util.LinkedHashSet;
28 import java.util.List;
29 import java.util.Objects;
30 import java.util.Set;
31 import java.util.jar.JarFile;
32 import java.util.jar.Manifest;
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.plugin.MojoExecutionException;
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.plugins.annotations.ResolutionScope;
39 import org.apache.maven.plugins.dependency.utils.DependencyStatusSets;
40 import org.apache.maven.plugins.dependency.utils.DependencyUtil;
41 import org.apache.maven.plugins.dependency.utils.filters.ResolveFileFilter;
42 import org.apache.maven.plugins.dependency.utils.markers.SourcesFileMarkerHandler;
43 import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
44 import org.apache.maven.shared.utils.logging.MessageBuilder;
45 import org.apache.maven.shared.utils.logging.MessageUtils;
46
47
48
49
50
51
52
53
54
55 @Mojo(
56 name = "resolve",
57 requiresDependencyResolution = ResolutionScope.TEST,
58 defaultPhase = LifecyclePhase.GENERATE_SOURCES,
59 threadSafe = true)
60
61 public class ResolveDependenciesMojo extends AbstractResolveMojo {
62
63 @Parameter(property = "outputEncoding", defaultValue = "${project.reporting.outputEncoding}")
64 private String outputEncoding;
65
66
67
68
69
70
71 @Parameter(property = "mdep.outputScope", defaultValue = "true")
72 protected boolean outputScope;
73
74
75
76
77 DependencyStatusSets results;
78
79
80
81
82
83
84 @Parameter(property = "sort", defaultValue = "false")
85 boolean sort;
86
87
88
89
90
91
92 @Parameter(property = "includeParents", defaultValue = "false")
93 boolean includeParents;
94
95
96
97
98
99
100 @Override
101 protected void doExecute() throws MojoExecutionException {
102
103 results = this.getDependencySets(false, includeParents);
104
105 String output = getOutput(outputAbsoluteArtifactFilename, outputScope, sort);
106 try {
107 if (outputFile == null) {
108 DependencyUtil.log(output, getLog());
109 } else {
110 String encoding = Objects.toString(outputEncoding, "UTF-8");
111 DependencyUtil.write(output, outputFile, appendOutput, encoding);
112 }
113 } catch (IOException e) {
114 throw new MojoExecutionException(e.getMessage(), e);
115 }
116 }
117
118
119
120
121 public DependencyStatusSets getResults() {
122 return this.results;
123 }
124
125 @Override
126 protected ArtifactsFilter getMarkedArtifactFilter() {
127 return new ResolveFileFilter(new SourcesFileMarkerHandler(this.markersDirectory));
128 }
129
130
131
132
133
134
135
136 public String getOutput(boolean outputAbsoluteArtifactFilename, boolean theOutputScope, boolean theSort) {
137 StringBuilder sb = new StringBuilder();
138 sb.append(System.lineSeparator());
139 sb.append("The following files have been resolved:");
140 sb.append(System.lineSeparator());
141 if (results.getResolvedDependencies() == null
142 || results.getResolvedDependencies().isEmpty()) {
143 sb.append(" none");
144 sb.append(System.lineSeparator());
145 } else {
146 sb.append(buildArtifactListOutput(
147 results.getResolvedDependencies(), outputAbsoluteArtifactFilename, theOutputScope, theSort));
148 }
149
150 if (results.getSkippedDependencies() != null
151 && !results.getSkippedDependencies().isEmpty()) {
152 sb.append(System.lineSeparator());
153 sb.append("The following files were skipped:");
154 sb.append(System.lineSeparator());
155 Set<Artifact> skippedDependencies = new LinkedHashSet<>(results.getSkippedDependencies());
156 sb.append(buildArtifactListOutput(
157 skippedDependencies, outputAbsoluteArtifactFilename, theOutputScope, theSort));
158 }
159
160 if (results.getUnResolvedDependencies() != null
161 && !results.getUnResolvedDependencies().isEmpty()) {
162 sb.append(System.lineSeparator());
163 sb.append("The following files have NOT been resolved:");
164 sb.append(System.lineSeparator());
165 Set<Artifact> unResolvedDependencies = new LinkedHashSet<>(results.getUnResolvedDependencies());
166 sb.append(buildArtifactListOutput(
167 unResolvedDependencies, outputAbsoluteArtifactFilename, theOutputScope, theSort));
168 }
169 sb.append(System.lineSeparator());
170
171 return sb.toString();
172 }
173
174 private StringBuilder buildArtifactListOutput(
175 Set<Artifact> artifacts, boolean outputAbsoluteArtifactFilename, boolean theOutputScope, boolean theSort) {
176 StringBuilder sb = new StringBuilder();
177 List<String> artifactStringList = new ArrayList<>();
178 for (Artifact artifact : artifacts) {
179 MessageBuilder messageBuilder = MessageUtils.buffer();
180
181 messageBuilder.a(" ");
182
183 if (theOutputScope) {
184 messageBuilder.a(artifact.toString());
185 } else {
186 messageBuilder.a(artifact.getId());
187 }
188
189 if (outputAbsoluteArtifactFilename) {
190 try {
191
192 String artifactFilename =
193 artifact.getFile().getAbsoluteFile().getPath();
194
195 messageBuilder.a(':').a(artifactFilename);
196 } catch (NullPointerException e) {
197
198 }
199 }
200
201 if (theOutputScope && artifact.isOptional()) {
202 messageBuilder.a(" (optional)");
203 }
204
205
206 if (artifact.getFile() != null) {
207 ModuleDescriptor moduleDescriptor = getModuleDescriptor(artifact.getFile());
208 if (moduleDescriptor != null) {
209 messageBuilder.project(" -- module " + moduleDescriptor.name);
210
211 if (moduleDescriptor.automatic) {
212 if ("MANIFEST".equals(moduleDescriptor.moduleNameSource)) {
213 messageBuilder.strong(" [auto]");
214 } else {
215 messageBuilder.warning(" (auto)");
216 }
217 }
218 }
219 }
220 artifactStringList.add(messageBuilder + System.lineSeparator());
221 }
222 if (theSort) {
223 Collections.sort(artifactStringList);
224 }
225 for (String artifactString : artifactStringList) {
226 sb.append(artifactString);
227 }
228 return sb;
229 }
230
231 private ModuleDescriptor getModuleDescriptor(File artifactFile) {
232 ModuleDescriptor moduleDescriptor = null;
233 try {
234
235 Class<?> moduleFinderClass = Class.forName("java.lang.module.ModuleFinder");
236
237 java.nio.file.Path path = artifactFile.toPath();
238
239 Method ofMethod = moduleFinderClass.getMethod("of", java.nio.file.Path[].class);
240 Object moduleFinderInstance = ofMethod.invoke(null, new Object[] {new java.nio.file.Path[] {path}});
241
242 Method findAllMethod = moduleFinderClass.getMethod("findAll");
243 Set<Object> moduleReferences = (Set<Object>) findAllMethod.invoke(moduleFinderInstance);
244
245
246 if (!moduleReferences.isEmpty()) {
247 Object moduleReference = moduleReferences.iterator().next();
248 Method descriptorMethod = moduleReference.getClass().getMethod("descriptor");
249 Object moduleDescriptorInstance = descriptorMethod.invoke(moduleReference);
250
251 Method nameMethod = moduleDescriptorInstance.getClass().getMethod("name");
252 String name = (String) nameMethod.invoke(moduleDescriptorInstance);
253
254 moduleDescriptor = new ModuleDescriptor();
255 moduleDescriptor.name = name;
256
257 Method isAutomaticMethod = moduleDescriptorInstance.getClass().getMethod("isAutomatic");
258 moduleDescriptor.automatic = (Boolean) isAutomaticMethod.invoke(moduleDescriptorInstance);
259
260 if (moduleDescriptor.automatic) {
261 if (artifactFile.isFile()) {
262 try (JarFile jarFile = new JarFile(artifactFile)) {
263 Manifest manifest = jarFile.getManifest();
264
265 if (manifest != null
266 && manifest.getMainAttributes().getValue("Automatic-Module-Name") != null) {
267 moduleDescriptor.moduleNameSource = "MANIFEST";
268 } else {
269 moduleDescriptor.moduleNameSource = "FILENAME";
270 }
271 } catch (IOException e) {
272
273 }
274 }
275 }
276 }
277 } catch (ClassNotFoundException | SecurityException | IllegalAccessException | IllegalArgumentException e) {
278
279 } catch (NoSuchMethodException e) {
280 e.printStackTrace();
281 } catch (InvocationTargetException e) {
282 Throwable cause = e.getCause();
283 while (cause.getCause() != null) {
284 cause = cause.getCause();
285 }
286 getLog().info("Can't extract module name from " + artifactFile.getName() + ": " + cause.getMessage());
287 }
288 return moduleDescriptor;
289 }
290
291 private class ModuleDescriptor {
292 String name;
293
294 boolean automatic = true;
295
296 String moduleNameSource;
297 }
298 }