1   package org.apache.maven.plugins.dependency.fromDependencies;
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  import java.io.BufferedReader;
23  import java.io.BufferedWriter;
24  import java.io.File;
25  import java.io.FileReader;
26  import java.io.FileWriter;
27  import java.io.IOException;
28  import java.io.Writer;
29  import java.util.ArrayList;
30  import java.util.Comparator;
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.Set;
34  import java.util.regex.Matcher;
35  import java.util.regex.Pattern;
36  
37  import org.apache.maven.artifact.Artifact;
38  import org.apache.maven.plugin.MojoExecutionException;
39  import org.apache.maven.plugins.annotations.Component;
40  import org.apache.maven.plugins.annotations.LifecyclePhase;
41  import org.apache.maven.plugins.annotations.Mojo;
42  import org.apache.maven.plugins.annotations.Parameter;
43  import org.apache.maven.plugins.annotations.ResolutionScope;
44  import org.apache.maven.plugins.dependency.utils.DependencyUtil;
45  import org.apache.maven.project.MavenProjectHelper;
46  import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
47  import org.apache.maven.shared.transfer.repository.RepositoryManager;
48  import org.codehaus.plexus.util.IOUtil;
49  import org.codehaus.plexus.util.StringUtils;
50  
51  
52  
53  
54  
55  
56  
57  
58  @Mojo( name = "build-classpath", requiresDependencyResolution = ResolutionScope.TEST, defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true )
59  
60  public class BuildClasspathMojo
61      extends AbstractDependencyFilterMojo
62      implements Comparator<Artifact>
63  {
64  
65      
66  
67  
68      @Parameter( property = "mdep.stripVersion", defaultValue = "false" )
69      private boolean stripVersion = false;
70  
71      
72  
73  
74      @Parameter( property = "mdep.stripClassifier", defaultValue = "false" )
75      private boolean stripClassifier = false;
76  
77      
78  
79  
80  
81      @Parameter( property = "mdep.prefix" )
82      private String prefix;
83  
84      
85  
86  
87      @Parameter( property = "mdep.outputProperty" )
88      private String outputProperty;
89  
90      
91  
92  
93      @Parameter( property = "mdep.outputFile" )
94      private File outputFile;
95  
96      
97  
98  
99      @Parameter( property = "mdep.regenerateFile", defaultValue = "false" )
100     private boolean regenerateFile;
101 
102     
103 
104 
105 
106 
107 
108 
109     @Parameter( property = "mdep.fileSeparator", defaultValue = "" )
110     private String fileSeparator;
111 
112     
113 
114 
115 
116 
117 
118 
119 
120     @Parameter( property = "mdep.pathSeparator", defaultValue = "" )
121     private String pathSeparator;
122 
123     
124 
125 
126 
127 
128 
129     @Parameter( property = "mdep.localRepoProperty", defaultValue = "" )
130     private String localRepoProperty;
131 
132     
133 
134 
135 
136 
137     @Parameter( defaultValue = "false" )
138     private boolean attach;
139 
140     
141 
142 
143 
144 
145     @Parameter( property = "mdep.outputFilterFile", defaultValue = "false" )
146     private boolean outputFilterFile;
147 
148     
149 
150 
151 
152 
153 
154     @Parameter( property = "mdep.useBaseVersion", defaultValue = "true" )
155     private boolean useBaseVersion = true;
156 
157     
158 
159 
160     @Component
161     private MavenProjectHelper projectHelper;
162 
163     @Component
164     private RepositoryManager repositoryManager;
165 
166     
167 
168 
169 
170 
171 
172     @Override
173     protected void doExecute()
174         throws MojoExecutionException
175     {
176         
177         boolean isFileSepSet = StringUtils.isNotEmpty( fileSeparator );
178         boolean isPathSepSet = StringUtils.isNotEmpty( pathSeparator );
179 
180         
181         if ( attach && StringUtils.isEmpty( localRepoProperty ) )
182         {
183             localRepoProperty = "${M2_REPO}";
184         }
185 
186         Set<Artifact> artifacts = getResolvedDependencies( true );
187 
188         if ( artifacts == null || artifacts.isEmpty() )
189         {
190             getLog().info( "No dependencies found." );
191         }
192 
193         List<Artifact> artList = new ArrayList<>( artifacts );
194 
195         StringBuilder sb = new StringBuilder();
196         Iterator<Artifact> i = artList.iterator();
197 
198         if ( i.hasNext() )
199         {
200             appendArtifactPath( i.next(), sb );
201 
202             while ( i.hasNext() )
203             {
204                 sb.append( isPathSepSet ? this.pathSeparator : File.pathSeparator );
205                 appendArtifactPath( i.next(), sb );
206             }
207         }
208 
209         String cpString = sb.toString();
210 
211         
212         
213         if ( isFileSepSet )
214         {
215             
216             final String pattern = Pattern.quote( File.separator );
217             final String replacement = Matcher.quoteReplacement( fileSeparator );
218             cpString = cpString.replaceAll( pattern, replacement );
219         }
220 
221         
222         if ( outputFilterFile )
223         {
224             cpString = "classpath=" + cpString;
225         }
226 
227         if ( outputProperty != null )
228         {
229             getProject().getProperties().setProperty( outputProperty, cpString );
230             if ( getLog().isDebugEnabled() )
231             {
232                 getLog().debug( outputProperty + " = " + cpString );
233             }
234         }
235 
236         if ( outputFile == null )
237         {
238             getLog().info( "Dependencies classpath:" + System.lineSeparator() + cpString );
239         }
240         else
241         {
242             if ( regenerateFile || !isUpdToDate( cpString ) )
243             {
244                 storeClasspathFile( cpString, outputFile );
245             }
246             else
247             {
248                 this.getLog().info( "Skipped writing classpath file '" + outputFile + "'.  No changes found." );
249             }
250         }
251         if ( attach )
252         {
253             attachFile( cpString );
254         }
255     }
256 
257     
258 
259 
260 
261     protected void attachFile( String cpString )
262         throws MojoExecutionException
263     {
264         File attachedFile = new File( getProject().getBuild().getDirectory(), "classpath" );
265         storeClasspathFile( cpString, attachedFile );
266 
267         projectHelper.attachArtifact( getProject(), attachedFile, "classpath" );
268     }
269 
270     
271 
272 
273 
274 
275 
276     protected void appendArtifactPath( Artifact art, StringBuilder sb )
277     {
278         if ( prefix == null )
279         {
280             String file = art.getFile().getPath();
281             
282             if ( StringUtils.isNotEmpty( localRepoProperty ) )
283             {
284                 File localBasedir = repositoryManager.getLocalRepositoryBasedir( session.getProjectBuildingRequest() );
285 
286                 file = StringUtils.replace( file, localBasedir.getAbsolutePath(), localRepoProperty );
287             }
288             sb.append( file );
289         }
290         else
291         {
292             
293             sb.append( prefix );
294             sb.append( File.separator );
295             sb.append( DependencyUtil.getFormattedFileName( art, this.stripVersion, this.prependGroupId,
296                                                             this.useBaseVersion, this.stripClassifier ) );
297         }
298     }
299 
300     
301 
302 
303 
304 
305 
306 
307     private boolean isUpdToDate( String cpString )
308     {
309         try
310         {
311             String oldCp = readClasspathFile();
312             return ( cpString == null ? oldCp == null : cpString.equals( oldCp ) );
313         }
314         catch ( Exception ex )
315         {
316             this.getLog().warn( "Error while reading old classpath file '" + outputFile + "' for up-to-date check: "
317                 + ex );
318 
319             return false;
320         }
321     }
322 
323     
324 
325 
326 
327 
328 
329     private void storeClasspathFile( String cpString, File out )
330         throws MojoExecutionException
331     {
332         
333         out.getParentFile().mkdirs();
334 
335         Writer w = null;
336         try
337         {
338             w = new BufferedWriter( new FileWriter( out ) );
339             w.write( cpString );
340             w.close();
341             w = null;
342             getLog().info( "Wrote classpath file '" + out + "'." );
343         }
344         catch ( IOException ex )
345         {
346             throw new MojoExecutionException( "Error while writing to classpath file '" + out + "': " + ex.toString(),
347                                               ex );
348         }
349         finally
350         {
351             IOUtil.close( w );
352         }
353     }
354 
355     
356 
357 
358 
359 
360 
361 
362     protected String readClasspathFile()
363         throws IOException
364     {
365         if ( outputFile == null )
366         {
367             throw new IllegalArgumentException( "The outputFile parameter "
368                 + "cannot be null if the file is intended to be read." );
369         }
370 
371         if ( !outputFile.isFile() )
372         {
373             return null;
374         }
375         StringBuilder sb = new StringBuilder();
376         BufferedReader r = null;
377 
378         try
379         {
380             r = new BufferedReader( new FileReader( outputFile ) );
381 
382             for ( String line = r.readLine(); line != null; line = r.readLine() )
383             {
384                 sb.append( line );
385             }
386 
387             r.close();
388             r = null;
389 
390             return sb.toString();
391         }
392         finally
393         {
394             IOUtil.close( r );
395         }
396     }
397 
398     
399 
400 
401 
402 
403 
404 
405 
406 
407     @Override
408     public int compare( Artifact art1, Artifact art2 )
409     {
410         if ( art1 == art2 )
411         {
412             return 0;
413         }
414         else if ( art1 == null )
415         {
416             return -1;
417         }
418         else if ( art2 == null )
419         {
420             return +1;
421         }
422 
423         String s1 = art1.getGroupId() + art1.getArtifactId() + art1.getVersion();
424         String s2 = art2.getGroupId() + art2.getArtifactId() + art2.getVersion();
425 
426         return s1.compareTo( s2 );
427     }
428 
429     @Override
430     protected ArtifactsFilter getMarkedArtifactFilter()
431     {
432         return null;
433     }
434 
435     
436 
437 
438     public void setOutputFile( File outputFile )
439     {
440         this.outputFile = outputFile;
441     }
442 
443     
444 
445 
446     public void setOutputProperty( String theOutputProperty )
447     {
448         this.outputProperty = theOutputProperty;
449     }
450 
451     
452 
453 
454     public void setFileSeparator( String theFileSeparator )
455     {
456         this.fileSeparator = theFileSeparator;
457     }
458 
459     
460 
461 
462     public void setPathSeparator( String thePathSeparator )
463     {
464         this.pathSeparator = thePathSeparator;
465     }
466 
467     
468 
469 
470     public void setPrefix( String thePrefix )
471     {
472         this.prefix = thePrefix;
473     }
474 
475     
476 
477 
478     public void setRegenerateFile( boolean theRegenerateFile )
479     {
480         this.regenerateFile = theRegenerateFile;
481     }
482 
483     
484 
485 
486     public boolean isStripVersion()
487     {
488         return this.stripVersion;
489     }
490 
491     
492 
493 
494     public void setStripVersion( boolean theStripVersion )
495     {
496         this.stripVersion = theStripVersion;
497     }
498 
499     
500 
501 
502     public void setLocalRepoProperty( String localRepoProperty )
503     {
504         this.localRepoProperty = localRepoProperty;
505     }
506 }