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