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