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 org.apache.maven.artifact.Artifact;
23 import org.apache.maven.plugin.MojoExecutionException;
24 import org.apache.maven.plugins.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.apache.maven.shared.repository.RepositoryManager;
33 import org.codehaus.plexus.util.IOUtil;
34 import org.codehaus.plexus.util.StringUtils;
35
36 import java.io.BufferedReader;
37 import java.io.BufferedWriter;
38 import java.io.File;
39 import java.io.FileReader;
40 import java.io.FileWriter;
41 import java.io.IOException;
42 import java.io.Writer;
43 import java.util.ArrayList;
44 import java.util.Comparator;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.Set;
48 import java.util.regex.Matcher;
49 import java.util.regex.Pattern;
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<Artifact>( 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:\n" + 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 writting 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 }