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