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