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,
317 this.useBaseVersion, this.stripClassifier ) );
318 }
319 }
320
321
322
323
324
325
326
327
328 private boolean isUpdToDate( String cpString )
329 {
330 try
331 {
332 String oldCp = readClasspathFile();
333 return ( cpString == null ? oldCp == null : cpString.equals( oldCp ) );
334 }
335 catch ( Exception ex )
336 {
337 this.getLog().warn(
338 "Error while reading old classpath file '" + outputFile + "' for up-to-date check: " + ex );
339
340 return false;
341 }
342 }
343
344
345
346
347
348
349
350 private void storeClasspathFile( String cpString, File out )
351 throws MojoExecutionException
352 {
353
354 out.getParentFile().mkdirs();
355
356 Writer w = null;
357 try
358 {
359 w = new BufferedWriter( new FileWriter( out ) );
360 w.write( cpString );
361 getLog().info( "Wrote classpath file '" + out + "'." );
362 }
363 catch ( IOException ex )
364 {
365 throw new MojoExecutionException( "Error while writting to classpath file '" + out + "': " + ex.toString(),
366 ex );
367 }
368 finally
369 {
370 IOUtil.close( w );
371 }
372 }
373
374
375
376
377
378
379
380
381 protected String readClasspathFile()
382 throws IOException
383 {
384 if ( outputFile == null )
385 {
386 throw new IllegalArgumentException(
387 "The outputFile parameter cannot be null if the file is intended to be read." );
388 }
389
390 if ( !outputFile.isFile() )
391 {
392 return null;
393 }
394 StringBuilder sb = new StringBuilder();
395 BufferedReader r = null;
396
397 try
398 {
399 r = new BufferedReader( new FileReader( outputFile ) );
400 String l;
401 while ( ( l = r.readLine() ) != null )
402 {
403 sb.append( l );
404 }
405
406 return sb.toString();
407 }
408 finally
409 {
410 IOUtil.close( r );
411 }
412 }
413
414
415
416
417
418
419
420
421
422
423 public int compare( Artifact art1, Artifact art2 )
424 {
425 if ( art1 == art2 )
426 {
427 return 0;
428 }
429 else if ( art1 == null )
430 {
431 return -1;
432 }
433 else if ( art2 == null )
434 {
435 return +1;
436 }
437
438 String s1 = art1.getGroupId() + art1.getArtifactId() + art1.getVersion();
439 String s2 = art2.getGroupId() + art2.getArtifactId() + art2.getVersion();
440
441 return s1.compareTo( s2 );
442 }
443
444 protected ArtifactsFilter getMarkedArtifactFilter()
445 {
446 return null;
447 }
448
449
450
451
452 public File getCpFile()
453 {
454 return this.outputFile;
455 }
456
457
458
459
460 public void setCpFile( File theCpFile )
461 {
462 this.outputFile = theCpFile;
463 }
464
465
466
467
468 public String getOutputProperty()
469 {
470 return this.outputProperty;
471 }
472
473
474
475
476 public void setOutputProperty( String theOutputProperty )
477 {
478 this.outputProperty = theOutputProperty;
479 }
480
481
482
483
484 public String getFileSeparator()
485 {
486 return this.fileSeparator;
487 }
488
489
490
491
492 public void setFileSeparator( String theFileSeparator )
493 {
494 this.fileSeparator = theFileSeparator;
495 }
496
497
498
499
500 public String getPathSeparator()
501 {
502 return this.pathSeparator;
503 }
504
505
506
507
508 public void setPathSeparator( String thePathSeparator )
509 {
510 this.pathSeparator = thePathSeparator;
511 }
512
513
514
515
516 public String getPrefix()
517 {
518 return this.prefix;
519 }
520
521
522
523
524 public void setPrefix( String thePrefix )
525 {
526 this.prefix = thePrefix;
527 }
528
529
530
531
532 public boolean isRegenerateFile()
533 {
534 return this.regenerateFile;
535 }
536
537
538
539
540 public void setRegenerateFile( boolean theRegenerateFile )
541 {
542 this.regenerateFile = theRegenerateFile;
543 }
544
545
546
547
548 public boolean isStripVersion()
549 {
550 return this.stripVersion;
551 }
552
553
554
555
556 public void setStripVersion( boolean theStripVersion )
557 {
558 this.stripVersion = theStripVersion;
559 }
560
561 public String getLocalRepoProperty()
562 {
563 return localRepoProperty;
564 }
565
566 public void setLocalRepoProperty( String localRepoProperty )
567 {
568 this.localRepoProperty = localRepoProperty;
569 }
570
571 public boolean isFileSepSet()
572 {
573 return isFileSepSet;
574 }
575
576 public void setFileSepSet( boolean isFileSepSet )
577 {
578 this.isFileSepSet = isFileSepSet;
579 }
580
581 public boolean isPathSepSet()
582 {
583 return isPathSepSet;
584 }
585
586 public void setPathSepSet( boolean isPathSepSet )
587 {
588 this.isPathSepSet = isPathSepSet;
589 }
590 }