1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  package org.codehaus.mojo.license;
26  
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.artifact.repository.ArtifactRepository;
29  import org.apache.maven.model.License;
30  import org.apache.maven.plugin.AbstractMojo;
31  import org.apache.maven.plugin.MojoExecutionException;
32  import org.apache.maven.project.MavenProject;
33  import org.codehaus.mojo.license.model.ProjectLicenseInfo;
34  
35  import java.io.File;
36  import java.io.FileInputStream;
37  import java.io.FileNotFoundException;
38  import java.io.IOException;
39  import java.net.MalformedURLException;
40  import java.net.URL;
41  import java.util.*;
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  public class DownloadLicensesMojo
55      extends AbstractMojo
56      implements MavenProjectDependenciesConfigurator
57  {
58  
59      
60  
61  
62  
63  
64  
65  
66      private MavenProject project;
67  
68      
69  
70  
71  
72  
73  
74  
75      private ArtifactRepository localRepository;
76  
77      
78  
79  
80  
81  
82  
83  
84      private List remoteRepositories;
85  
86      
87  
88  
89  
90  
91  
92      private File licensesConfigFile;
93  
94      
95  
96  
97  
98  
99  
100     private File licensesOutputDirectory;
101 
102     
103 
104 
105 
106 
107 
108     private File licensesOutputFile;
109 
110     
111 
112 
113 
114 
115 
116     private String excludedScopes;
117 
118     
119 
120 
121 
122 
123 
124     private String includedScopes;
125 
126     
127 
128 
129 
130 
131 
132     private boolean offline;
133 
134     
135 
136 
137 
138 
139 
140     private boolean quiet;
141 
142     
143 
144 
145 
146 
147 
148     private boolean includeTransitiveDependencies;
149 
150     
151 
152 
153 
154 
155 
156 
157     private DependenciesTool dependenciesTool;
158 
159     
160 
161 
162 
163     private Set<String> downloadedLicenseURLs = new HashSet<String>();
164 
165     
166 
167 
168     public void execute()
169         throws MojoExecutionException
170     {
171 
172         if ( offline )
173         {
174 
175             getLog().warn( "Offline flag is on, download-licenses goal is skip." );
176             return;
177         }
178         initDirectories();
179 
180         Map<String, ProjectLicenseInfo> configuredDepLicensesMap = new HashMap<String, ProjectLicenseInfo>();
181 
182         
183         if ( licensesOutputFile.exists() )
184         {
185             loadLicenseInfo( configuredDepLicensesMap, licensesOutputFile, true );
186         }
187 
188         
189         if ( licensesConfigFile.exists() )
190         {
191             loadLicenseInfo( configuredDepLicensesMap, licensesConfigFile, false );
192         }
193 
194         SortedMap<String, MavenProject> dependencies =
195             dependenciesTool.loadProjectDependencies( project, this, localRepository, remoteRepositories, null );
196 
197         
198         List<ProjectLicenseInfo> depProjectLicenses = new ArrayList<ProjectLicenseInfo>();
199 
200         for ( MavenProject project : dependencies.values() )
201         {
202             Artifact artifact = project.getArtifact();
203             getLog().debug( "Checking licenses for project " + artifact );
204             String artifactProjectId = getArtifactProjectId( artifact );
205             ProjectLicenseInfo depProject;
206             if ( configuredDepLicensesMap.containsKey( artifactProjectId ) )
207             {
208                 depProject = configuredDepLicensesMap.get( artifactProjectId );
209                 depProject.setVersion( artifact.getVersion() );
210             }
211             else
212             {
213                 depProject = createDependencyProject( project );
214             }
215             downloadLicenses( depProject );
216             depProjectLicenses.add( depProject );
217         }
218 
219         try
220         {
221             LicenseSummaryWriter.writeLicenseSummary( depProjectLicenses, licensesOutputFile );
222         }
223         catch ( Exception e )
224         {
225             throw new MojoExecutionException( "Unable to write license summary file: " + licensesOutputFile, e );
226         }
227 
228     }
229 
230     private void initDirectories()
231         throws MojoExecutionException
232     {
233         try
234         {
235             FileUtil.createDirectoryIfNecessary( licensesOutputDirectory );
236 
237             FileUtil.createDirectoryIfNecessary( licensesOutputFile.getParentFile() );
238         }
239         catch ( IOException e )
240         {
241             throw new MojoExecutionException( "Unable to create a directory...", e );
242         }
243     }
244 
245     
246 
247 
248 
249 
250 
251 
252 
253 
254     private void loadLicenseInfo( Map<String, ProjectLicenseInfo> configuredDepLicensesMap, File licenseConfigFile,
255                                   boolean previouslyDownloaded )
256         throws MojoExecutionException
257     {
258         FileInputStream fis = null;
259         try
260         {
261             fis = new FileInputStream( licenseConfigFile );
262             List<ProjectLicenseInfo> licensesList = LicenseSummaryReader.parseLicenseSummary( fis );
263             for ( ProjectLicenseInfo dep : licensesList )
264             {
265                 configuredDepLicensesMap.put( dep.getId(), dep );
266                 if ( previouslyDownloaded )
267                 {
268                     for ( License license : dep.getLicenses() )
269                     {
270                         
271                         downloadedLicenseURLs.add( license.getUrl() );
272                     }
273                 }
274             }
275         }
276         catch ( Exception e )
277         {
278             throw new MojoExecutionException( "Unable to parse license summary output file: " + licenseConfigFile, e );
279         }
280         finally
281         {
282             FileUtil.tryClose( fis );
283         }
284     }
285 
286     
287 
288 
289 
290 
291 
292     public String getArtifactProjectId( Artifact artifact )
293     {
294         return artifact.getGroupId() + ":" + artifact.getArtifactId();
295     }
296 
297     
298 
299 
300 
301 
302 
303     public ProjectLicenseInfo createDependencyProject( MavenProject depMavenProject )
304     {
305         ProjectLicenseInfo dependencyProject =
306             new ProjectLicenseInfo( depMavenProject.getGroupId(), depMavenProject.getArtifactId(),
307                                     depMavenProject.getVersion() );
308         List<?> licenses = depMavenProject.getLicenses();
309         for ( Object license : licenses )
310         {
311             dependencyProject.addLicense( (License) license );
312         }
313         return dependencyProject;
314     }
315 
316     
317 
318 
319 
320 
321 
322 
323 
324     private String getLicenseFileName( License license )
325         throws MalformedURLException
326     {
327         URL licenseUrl = new URL( license.getUrl() );
328         File licenseUrlFile = new File( licenseUrl.getPath() );
329         String licenseFileName = licenseUrlFile.getName();
330 
331         if ( license.getName() != null )
332         {
333             licenseFileName = license.getName() + " - " + licenseUrlFile.getName();
334         }
335 
336         
337         final String DEFAULT_EXTENSION = ".txt";
338         int extensionIndex = licenseFileName.lastIndexOf( "." );
339         if ( extensionIndex == -1 || extensionIndex > ( licenseFileName.length() - 3 ) )
340         {
341             
342             licenseFileName = licenseFileName + DEFAULT_EXTENSION;
343         }
344 
345         
346         licenseFileName = licenseFileName.toLowerCase();
347 
348         return licenseFileName;
349     }
350 
351     
352 
353 
354 
355 
356     private void downloadLicenses( ProjectLicenseInfo depProject )
357     {
358         getLog().debug( "Downloading license(s) for project " + depProject );
359 
360         List<License> licenses = depProject.getLicenses();
361 
362         if ( depProject.getLicenses() == null || depProject.getLicenses().isEmpty() )
363         {
364             if ( !quiet )
365             {
366                 getLog().warn( "No license information available for: " + depProject );
367             }
368             return;
369         }
370 
371         for ( License license : licenses )
372         {
373             try
374             {
375                 String licenseFileName = getLicenseFileName( license );
376 
377                 File licenseOutputFile = new File( licensesOutputDirectory, licenseFileName );
378                 if ( licenseOutputFile.exists() )
379                 {
380                     continue;
381                 }
382 
383                 if ( !downloadedLicenseURLs.contains( license.getUrl() ) )
384                 {
385                     LicenseDownloader.downloadLicense( license.getUrl(), licenseOutputFile );
386                     downloadedLicenseURLs.add( license.getUrl() );
387                 }
388             }
389             catch ( MalformedURLException e )
390             {
391                 if ( !quiet )
392                 {
393                     getLog().warn( "POM for dependency " + depProject.toString() + " has an invalid license URL: " +
394                                        license.getUrl() );
395                 }
396             }
397             catch ( FileNotFoundException e )
398             {
399                 if ( !quiet )
400                 {
401                     getLog().warn( "POM for dependency " + depProject.toString() +
402                                        " has a license URL that returns file not found: " + license.getUrl() );
403                 }
404             }
405             catch ( IOException e )
406             {
407                 getLog().warn( "Unable to retrieve license for dependency: " + depProject.toString() );
408                 getLog().warn( license.getUrl() );
409                 getLog().warn( e.getMessage() );
410             }
411 
412         }
413 
414     }
415 
416     public MavenProject getProject()
417     {
418         return project;
419     }
420 
421     public ArtifactRepository getLocalRepository()
422     {
423         return localRepository;
424     }
425 
426     public List getRemoteRepositories()
427     {
428         return remoteRepositories;
429     }
430 
431     
432 
433 
434     public boolean isIncludeTransitiveDependencies()
435     {
436         return includeTransitiveDependencies;
437     }
438 
439     
440 
441 
442     public List<String> getExcludedScopes()
443     {
444         String[] split = excludedScopes == null ? new String[0] : excludedScopes.split( "," );
445         return Arrays.asList( split );
446     }
447 
448     public void setExcludedScopes( String excludedScopes )
449     {
450         this.excludedScopes = excludedScopes;
451     }
452 
453     
454 
455 
456     public List<String> getIncludedScopes()
457     {
458         String[] split = includedScopes == null ? new String[0] : includedScopes.split( "," );
459         return Arrays.asList( split );
460     }
461 
462     public void setIncludedScopes( String includedScopes )
463     {
464         this.includedScopes = includedScopes;
465     }
466 
467     
468 
469     
470 
471 
472     public String getIncludedArtifacts()
473     {
474         return null;
475     }
476 
477     
478 
479     
480 
481 
482     public String getIncludedGroups()
483     {
484         return null;
485     }
486 
487     
488 
489     
490 
491 
492     public String getExcludedGroups()
493     {
494         return null;
495     }
496 
497     
498 
499     
500 
501 
502     public String getExcludedArtifacts()
503     {
504         return null;
505     }
506 
507     
508 
509 
510     public boolean isVerbose()
511     {
512         return getLog().isDebugEnabled();
513     }
514 }