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, threadSafe = true )
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
149
150 @Parameter( property = "mdep.useBaseVersion", defaultValue = "true" )
151 protected boolean useBaseVersion = true;
152
153
154
155
156 @Component
157 private MavenProjectHelper projectHelper;
158
159 boolean isFileSepSet = true;
160
161 boolean isPathSepSet = true;
162
163
164
165
166
167
168
169
170 public void execute()
171 throws MojoExecutionException
172 {
173
174 if ( cpFile != null )
175 {
176 getLog().warn( "The parameter cpFile is deprecated. Use outputFile instead." );
177 this.outputFile = cpFile;
178 }
179
180
181 isFileSepSet = StringUtils.isNotEmpty( fileSeparator );
182 isPathSepSet = StringUtils.isNotEmpty( pathSeparator );
183
184
185 if ( attach && StringUtils.isEmpty( localRepoProperty ) )
186 {
187 localRepoProperty = "${M2_REPO}";
188 }
189
190 Set<Artifact> artifacts = getResolvedDependencies( true );
191
192 if ( artifacts == null || artifacts.isEmpty() )
193 {
194 getLog().info( "No dependencies found." );
195 }
196
197 List<Artifact> artList = new ArrayList<Artifact>( artifacts );
198
199 StringBuilder sb = new StringBuilder();
200 Iterator<Artifact> i = artList.iterator();
201
202 if ( i.hasNext() )
203 {
204 appendArtifactPath( i.next(), sb );
205
206 while ( i.hasNext() )
207 {
208 sb.append( isPathSepSet ? this.pathSeparator : File.pathSeparator );
209 appendArtifactPath( (Artifact) i.next(), sb );
210 }
211 }
212
213 String cpString = sb.toString();
214
215
216
217 if ( isFileSepSet )
218 {
219
220 final String pattern = Pattern.quote( File.separator );
221 final String replacement = Matcher.quoteReplacement( fileSeparator );
222 cpString = cpString.replaceAll( pattern, replacement );
223 }
224
225
226 if ( outputFilterFile )
227 {
228 cpString = "classpath=" + cpString;
229 }
230
231 if ( outputFile == null )
232 {
233 getLog().info( "Dependencies classpath:\n" + cpString );
234 }
235 else
236 {
237 if ( regenerateFile || !isUpdToDate( cpString ) )
238 {
239 storeClasspathFile( cpString, outputFile );
240 }
241 else
242 {
243 this.getLog().info( "Skipped writing classpath file '" + outputFile + "'. No changes found." );
244 }
245 }
246 if ( attach )
247 {
248 attachFile( cpString );
249 }
250 }
251
252 protected void attachFile( String cpString )
253 throws MojoExecutionException
254 {
255 File attachedFile = new File( project.getBuild().getDirectory(), "classpath" );
256 storeClasspathFile( cpString, attachedFile );
257
258 projectHelper.attachArtifact( project, attachedFile, "classpath" );
259 }
260
261
262
263
264
265
266
267 protected void appendArtifactPath( Artifact art, StringBuilder sb )
268 {
269 if ( prefix == null )
270 {
271 String file = art.getFile().getPath();
272
273 if ( StringUtils.isNotEmpty( localRepoProperty ) )
274 {
275 file = StringUtils.replace( file, getLocal().getBasedir(), localRepoProperty );
276 }
277 sb.append( file );
278 }
279 else
280 {
281
282 sb.append( prefix );
283 sb.append( File.separator );
284 sb.append( DependencyUtil.getFormattedFileName( art, this.stripVersion, this.prependGroupId, this.useBaseVersion ) );
285 }
286 }
287
288
289
290
291
292
293
294
295 private boolean isUpdToDate( String cpString )
296 {
297 try
298 {
299 String oldCp = readClasspathFile();
300 return ( cpString == oldCp || ( cpString != null && cpString.equals( oldCp ) ) );
301 }
302 catch ( Exception ex )
303 {
304 this.getLog().warn(
305 "Error while reading old classpath file '" + outputFile + "' for up-to-date check: " + ex );
306
307 return false;
308 }
309 }
310
311
312
313
314
315
316
317 private void storeClasspathFile( String cpString, File out )
318 throws MojoExecutionException
319 {
320
321 out.getParentFile().mkdirs();
322
323 Writer w = null;
324 try
325 {
326 w = new BufferedWriter( new FileWriter( out ) );
327 w.write( cpString );
328 getLog().info( "Wrote classpath file '" + out + "'." );
329 }
330 catch ( IOException ex )
331 {
332 throw new MojoExecutionException( "Error while writting to classpath file '" + out + "': " + ex.toString(),
333 ex );
334 }
335 finally
336 {
337 IOUtil.close( w );
338 }
339 }
340
341
342
343
344
345
346
347
348 protected String readClasspathFile()
349 throws IOException
350 {
351 if ( outputFile == null )
352 {
353 throw new IllegalArgumentException(
354 "The outputFile parameter cannot be null if the file is intended to be read." );
355 }
356
357 if ( !outputFile.isFile() )
358 {
359 return null;
360 }
361 StringBuilder sb = new StringBuilder();
362 BufferedReader r = null;
363
364 try
365 {
366 r = new BufferedReader( new FileReader( outputFile ) );
367 String l;
368 while ( ( l = r.readLine() ) != null )
369 {
370 sb.append( l );
371 }
372
373 return sb.toString();
374 }
375 finally
376 {
377 IOUtil.close( r );
378 }
379 }
380
381
382
383
384
385
386
387
388
389
390 public int compare( Artifact art1, Artifact art2 )
391 {
392 if ( art1 == art2 )
393 {
394 return 0;
395 }
396 else if ( art1 == null )
397 {
398 return -1;
399 }
400 else if ( art2 == null )
401 {
402 return +1;
403 }
404
405 String s1 = art1.getGroupId() + art1.getArtifactId() + art1.getVersion();
406 String s2 = art2.getGroupId() + art2.getArtifactId() + art2.getVersion();
407
408 return s1.compareTo( s2 );
409 }
410
411 protected ArtifactsFilter getMarkedArtifactFilter()
412 {
413 return null;
414 }
415
416
417
418
419 public File getCpFile()
420 {
421 return this.outputFile;
422 }
423
424
425
426
427 public void setCpFile( File theCpFile )
428 {
429 this.outputFile = theCpFile;
430 }
431
432
433
434
435 public String getFileSeparator()
436 {
437 return this.fileSeparator;
438 }
439
440
441
442
443 public void setFileSeparator( String theFileSeparator )
444 {
445 this.fileSeparator = theFileSeparator;
446 }
447
448
449
450
451 public String getPathSeparator()
452 {
453 return this.pathSeparator;
454 }
455
456
457
458
459 public void setPathSeparator( String thePathSeparator )
460 {
461 this.pathSeparator = thePathSeparator;
462 }
463
464
465
466
467 public String getPrefix()
468 {
469 return this.prefix;
470 }
471
472
473
474
475 public void setPrefix( String thePrefix )
476 {
477 this.prefix = thePrefix;
478 }
479
480
481
482
483 public boolean isRegenerateFile()
484 {
485 return this.regenerateFile;
486 }
487
488
489
490
491 public void setRegenerateFile( boolean theRegenerateFile )
492 {
493 this.regenerateFile = theRegenerateFile;
494 }
495
496
497
498
499 public boolean isStripVersion()
500 {
501 return this.stripVersion;
502 }
503
504
505
506
507 public void setStripVersion( boolean theStripVersion )
508 {
509 this.stripVersion = theStripVersion;
510 }
511
512 public String getLocalRepoProperty()
513 {
514 return localRepoProperty;
515 }
516
517 public void setLocalRepoProperty( String localRepoProperty )
518 {
519 this.localRepoProperty = localRepoProperty;
520 }
521
522 public boolean isFileSepSet()
523 {
524 return isFileSepSet;
525 }
526
527 public void setFileSepSet( boolean isFileSepSet )
528 {
529 this.isFileSepSet = isFileSepSet;
530 }
531
532 public boolean isPathSepSet()
533 {
534 return isPathSepSet;
535 }
536
537 public void setPathSepSet( boolean isPathSepSet )
538 {
539 this.isPathSepSet = isPathSepSet;
540 }
541 }