1 package org.apache.maven.plugin.cxx;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import org.apache.maven.artifact.Artifact;
22 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
23 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
24 import org.apache.maven.plugin.MojoExecutionException;
25 import org.apache.maven.plugin.dependency.utils.DependencyStatusSets;
26 import org.apache.maven.plugin.dependency.utils.DependencyUtil;
27 import org.apache.maven.plugin.dependency.utils.filters.MarkerFileFilter;
28 import org.apache.maven.plugin.dependency.utils.markers.DefaultFileMarkerHandler;
29 import org.apache.maven.plugins.annotations.LifecyclePhase;
30 import org.apache.maven.plugins.annotations.Mojo;
31 import org.apache.maven.plugins.annotations.Parameter;
32 import org.apache.maven.plugins.annotations.Component;
33 import org.apache.maven.plugins.annotations.ResolutionScope;
34 import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
35
36 import org.codehaus.plexus.util.StringUtils;
37
38 import java.io.File;
39 import java.io.IOException;
40 import java.util.Set;
41 import java.util.ArrayList;
42 import java.util.regex.Pattern;
43 import java.util.Properties;
44
45 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
46 import org.apache.maven.plugin.cxx.utils.ClassifierRegexFilter;
47 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
48 import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
49 import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
50 import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
51 import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
52 import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
53 import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
54
55 import org.apache.maven.project.MavenProject;
56 import org.apache.maven.project.MavenProjectBuilder;
57 import org.apache.maven.project.ProjectBuildingException;
58 import org.apache.maven.model.Scm;
59
60 import org.apache.maven.plugin.cxx.utils.SourceTarget;
61 import org.apache.maven.plugin.cxx.utils.Credential;
62 import org.apache.maven.plugin.cxx.utils.svn.SvnService;
63 import org.apache.maven.plugin.cxx.utils.svn.SvnInfo;
64 import org.apache.maven.plugin.cxx.utils.svn.SvnExternalEntry;
65 import org.apache.maven.plugin.cxx.utils.svn.SvnExternalsEntries;
66
67 import org.apache.maven.settings.Settings;
68
69
70
71
72
73 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
74
75
76
77
78
79
80
81 @Mojo( name = "scm-dependencies", requiresDependencyResolution = ResolutionScope.TEST,
82 defaultPhase = LifecyclePhase.VALIDATE, threadSafe = true )
83 public class ScmDependenciesMojo
84 extends org.apache.maven.plugin.dependency.fromDependencies.AbstractDependencyFilterMojo
85 {
86
87
88
89
90
91 @Parameter( property = "basedir", readonly = true, required = true )
92 protected File basedir;
93
94
95
96
97
98
99 @Parameter( property = "sourceSubdir", defaultValue = "." )
100 protected String sourceSubdir;
101
102
103
104
105
106
107 @Parameter( property = "sourceFreezeRevision", defaultValue = "false" )
108 protected boolean sourceFreezeRevision;
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 @Parameter( )
124 protected String[] sourceTargetDirRemovePrefixes = null;
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 @Parameter( )
145 private SourceTarget[] sourceTargets = null;
146
147
148
149
150
151
152
153 @Parameter( property = "includeRegexClassifiers", defaultValue = "" )
154 protected String includeRegexClassifiers;
155
156
157
158
159
160
161
162 @Parameter( property = "excludeRegexClassifiers", defaultValue = "" )
163 protected String excludeRegexClassifiers;
164
165
166
167
168
169
170 @Parameter( property = "connectionType", defaultValue = "connection" )
171 protected String connectionType;
172
173
174
175
176
177
178
179
180
181 @Parameter( property = "username" )
182 private String username = null;
183
184
185
186
187
188
189
190
191
192 @Parameter( property = "password" )
193 private String password = null;
194
195
196
197
198
199
200
201
202
203
204 @Parameter( property = "settingsServerId" )
205 private String settingsServerId = null;
206
207
208
209
210
211
212 @Parameter( defaultValue = "${settings}", readonly = true )
213 private Settings settings;
214
215
216
217
218
219
220
221
222
223 @Component( hint = "mng-4384" )
224 private SecDispatcher secDispatcher;
225
226
227
228
229
230
231
232 protected ArtifactsFilter getMarkedArtifactFilter()
233 {
234 return new MarkerFileFilter( this.overWriteReleases, this.overWriteSnapshots, this.overWriteIfNewer,
235 new DefaultFileMarkerHandler( this.markersDirectory ) );
236 }
237
238
239
240
241
242 @Component
243 MavenProjectBuilder myProjectBuilder;
244
245
246
247
248
249 private MavenProject buildProjectFromArtifact( Artifact artifact )
250 throws MojoExecutionException
251 {
252 try
253 {
254 return myProjectBuilder.buildFromRepository( artifact, remoteRepos, getLocal() );
255 }
256 catch ( ProjectBuildingException e )
257 {
258 throw new MojoExecutionException( e.getMessage(), e );
259 }
260 }
261
262
263
264
265
266 private void addParentArtifacts( MavenProject project, Set<Artifact> artifacts )
267 throws MojoExecutionException
268 {
269 while ( project.hasParent() )
270 {
271 project = project.getParent();
272
273 if ( project.getArtifact() == null )
274 {
275
276 Artifact artifact =
277 factory.createBuildArtifact( project.getGroupId(), project.getArtifactId(), project.getVersion(),
278 project.getPackaging() );
279 project.setArtifact( artifact );
280 }
281
282 if ( !artifacts.add( project.getArtifact() ) )
283 {
284
285 break;
286 }
287 try
288 {
289 resolver.resolve( project.getArtifact(), this.remoteRepos, this.getLocal() );
290 }
291 catch ( ArtifactResolutionException e )
292 {
293 throw new MojoExecutionException( e.getMessage(), e );
294 }
295 catch ( ArtifactNotFoundException e )
296 {
297 throw new MojoExecutionException( e.getMessage(), e );
298 }
299 }
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313
314 protected DependencyStatusSets getDependencySets( boolean stopOnFailure, boolean includeParents )
315 throws MojoExecutionException
316 {
317
318 FilterArtifacts filter = new FilterArtifacts();
319
320 filter.addFilter( new ProjectTransitivityFilter( project.getDependencyArtifacts(), this.excludeTransitive ) );
321
322 filter.addFilter( new ScopeFilter( DependencyUtil.cleanToBeTokenizedString( this.includeScope ),
323 DependencyUtil.cleanToBeTokenizedString( this.excludeScope ) ) );
324
325
326
327 filter.addFilter( new TypeFilter( DependencyUtil.cleanToBeTokenizedString( "pom" ),
328 DependencyUtil.cleanToBeTokenizedString( null ) ) );
329
330 filter.addFilter( new ClassifierFilter( DependencyUtil.cleanToBeTokenizedString( this.includeClassifiers ),
331 DependencyUtil.cleanToBeTokenizedString( this.excludeClassifiers ) ) );
332
333 filter.addFilter( new ClassifierRegexFilter (
334 DependencyUtil.cleanToBeTokenizedString( this.includeRegexClassifiers ),
335 DependencyUtil.cleanToBeTokenizedString( this.excludeRegexClassifiers ) ) );
336
337 filter.addFilter( new GroupIdFilter( DependencyUtil.cleanToBeTokenizedString( this.includeGroupIds ),
338 DependencyUtil.cleanToBeTokenizedString( this.excludeGroupIds ) ) );
339
340 filter.addFilter( new ArtifactIdFilter( DependencyUtil.cleanToBeTokenizedString( this.includeArtifactIds ),
341 DependencyUtil.cleanToBeTokenizedString( this.excludeArtifactIds ) ) );
342
343
344
345 @SuppressWarnings( "unchecked" ) Set<Artifact> artifacts = project.getArtifacts();
346
347 if ( includeParents )
348 {
349
350 for ( Artifact dep : new ArrayList<Artifact>( artifacts ) )
351 {
352 addParentArtifacts( buildProjectFromArtifact( dep ), artifacts );
353 }
354
355
356 addParentArtifacts( project, artifacts );
357 }
358
359
360 try
361 {
362 artifacts = filter.filter( artifacts );
363 }
364 catch ( ArtifactFilterException e )
365 {
366 throw new MojoExecutionException( e.getMessage(), e );
367 }
368
369
370 DependencyStatusSets status;
371 if ( StringUtils.isNotEmpty( classifier ) )
372 {
373 status = getClassifierTranslatedDependencies( artifacts, stopOnFailure );
374 }
375 else
376 {
377 status = filterMarkedDependencies( artifacts );
378 }
379
380 return status;
381 }
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 SvnExternalEntry buildExternalEntryFromProvidedInfos( String targetDir, Artifact artifact,
397 MavenProject dependencyProject, SvnInfo dependencySvnInfo, SvnInfo rootSvnInfo )
398 {
399 if ( null != sourceTargetDirRemovePrefixes )
400 {
401 for ( String sourceTargetDirRemovePrefix : sourceTargetDirRemovePrefixes )
402 {
403 targetDir = targetDir.replaceFirst( "^" + Pattern.quote( sourceTargetDirRemovePrefix ), "" );
404 }
405 }
406 targetDir = targetDir.replaceFirst( "^/", "" );
407
408 SvnExternalEntry external = null;
409 File f = new File( targetDir );
410 try
411 {
412 f.getCanonicalPath();
413 }
414 catch ( IOException e )
415 {
416 getLog().warn( "targetPath for external " + artifactToString( artifact ) + " is not a path : "
417 + targetDir );
418 return external;
419 }
420 external = new SvnExternalEntry();
421
422 external.targetDir = targetDir;
423
424 external.origin = StringUtils.equals( rootSvnInfo.getSvnRoot(), dependencySvnInfo.getSvnRoot() )
425 ? dependencySvnInfo.getSvnRelativeUrl() : dependencySvnInfo.getSvnUrl();
426
427 external.revision = sourceFreezeRevision
428 ? "-r" + String.valueOf( dependencySvnInfo.getRevision() ) : null;
429
430 return external;
431 }
432
433
434 SvnExternalEntry buildCurrentDependencyExternalFromPluginsConfig( Artifact artifact, MavenProject dependencyProject,
435 SvnInfo dependencySvnInfo, SvnInfo rootSvnInfo )
436 {
437 SvnExternalEntry external = null;
438
439 if ( null != sourceTargets )
440 {
441 for ( SourceTarget curExt : sourceTargets )
442 {
443 if ( curExt.dependencyMatch( artifact ) )
444 {
445 getLog().debug( "Dependency " + curExt.dependency + " match " + artifactToString( artifact ) );
446 external = buildExternalEntryFromProvidedInfos( curExt.targetDir, artifact,
447 dependencyProject, dependencySvnInfo, rootSvnInfo );
448 if ( null != external )
449 {
450 getLog().info( "Dependency " + artifactToString( artifact )
451 + " external entry computed with plugin config is : " + external.toString() );
452 }
453 break;
454 }
455 }
456 }
457 return external;
458 }
459
460 SvnExternalEntry buildCurrentDependencyFromDependencyConfig( Artifact artifact, MavenProject dependencyProject,
461 SvnInfo dependencySvnInfo, SvnInfo rootSvnInfo )
462 {
463 SvnExternalEntry external = null;
464
465 Properties ps = dependencyProject.getProperties();
466 if ( null != ps )
467 {
468 String targetDir = ps.getProperty( "scm.dependencies.source.targetDir" );
469 if ( ! StringUtils.isEmpty( targetDir ) )
470 {
471 external = buildExternalEntryFromProvidedInfos( targetDir, artifact,
472 dependencyProject, dependencySvnInfo, rootSvnInfo );
473 if ( null != external )
474 {
475 getLog().info( "Dependency " + artifactToString( artifact )
476 + " external entry computed with 'scm.dependencies.source.targetDir' property is : "
477 + external.toString() );
478 }
479 }
480 else
481 {
482 getLog().info( "Maven project of dependency " + artifactToString( artifact )
483 + " do not define property 'scm.dependencies.source.targetDir'" );
484 }
485 }
486 else
487 {
488 getLog().info( "Maven project of dependency " + artifactToString( artifact ) + " has no properties" );
489 }
490 return external;
491 }
492
493 SvnExternalEntry buildCurrentDependencyExternalDefault( Artifact artifact, MavenProject dependencyProject,
494 SvnInfo dependencySvnInfo, SvnInfo rootSvnInfo )
495 {
496 SvnExternalEntry external = null;
497
498 String targetDir = dependencyProject.getGroupId() + "." + dependencyProject.getArtifactId();
499
500 if ( null != sourceTargetDirRemovePrefixes )
501 {
502 for ( String sourceTargetDirRemovePrefix : sourceTargetDirRemovePrefixes )
503 {
504 targetDir = targetDir.replaceFirst( "^" + Pattern.quote( sourceTargetDirRemovePrefix ), "" );
505 }
506 }
507 targetDir = targetDir.replaceAll( Pattern.quote( "." ), "/" );
508
509 external = buildExternalEntryFromProvidedInfos( targetDir, artifact,
510 dependencyProject, dependencySvnInfo, rootSvnInfo );
511 if ( null != external )
512 {
513 getLog().info( "Dependency " + artifactToString( artifact ) + " defaut computed external entry is : "
514 + external.toString() );
515 }
516 return external;
517 }
518
519 public String artifactToString( Artifact artifact )
520 {
521 StringBuffer dependencyStr = new StringBuffer();
522 dependencyStr.append( artifact.getGroupId() );
523 dependencyStr.append( ":" );
524 dependencyStr.append( artifact.getArtifactId() );
525 dependencyStr.append( ":" );
526 dependencyStr.append( artifact.getVersion() );
527 dependencyStr.append( ":" );
528 dependencyStr.append( artifact.getType() );
529 return dependencyStr.toString();
530 }
531
532 protected void doExecute()
533 throws MojoExecutionException
534 {
535 DependencyStatusSets dss = getDependencySets( true );
536
537
538 SvnInfo externalsSvnInfo = null;
539 SvnExternalsEntries externalsEntries = null;
540 File targetSourceDir = null;
541
542 for ( Artifact artifact : dss.getResolvedDependencies() )
543 {
544 String dependencyStr = artifactToString( artifact );
545
546 MavenProject dependencyProject = buildProjectFromArtifact( artifact );
547 Scm scm = dependencyProject.getScm();
548
549 if ( scm == null )
550 {
551 throw new MojoExecutionException( "No SCM specified for artifact " + dependencyStr );
552 }
553
554 String scmUri = scm.getConnection();
555 if ( StringUtils.equals( connectionType, "developerConnection" ) )
556 {
557 scmUri = scm.getDeveloperConnection();
558 }
559
560 if ( StringUtils.isEmpty( scmUri ) )
561 {
562 throw new MojoExecutionException( "No SCM Uri specified for artifact " + dependencyStr );
563 }
564
565 String[] scmType = scmUri.split( ":", 3 );
566
567 if ( scmType.length < 3 || ! StringUtils.equalsIgnoreCase( scmType[0], "scm" ) )
568 {
569 throw new MojoExecutionException( "SCM Uri content invalide : " + scmUri );
570 }
571
572 if ( StringUtils.equalsIgnoreCase( scmType[1], "svn" ) )
573 {
574 String dependencySvnUri = scmType[2];
575
576
577 if ( null == externalsSvnInfo || null == externalsEntries )
578 {
579 targetSourceDir = new File( basedir.toString() + File.separator + sourceSubdir );
580 if ( ! targetSourceDir.isDirectory() )
581 {
582 throw new MojoExecutionException( "Svn externals dir does not exists or is not a directory : "
583 + targetSourceDir );
584 }
585
586 externalsSvnInfo = SvnService.getSvnInfo( basedir,
587 null, targetSourceDir.getAbsolutePath(), getLog(), false );
588
589 if ( ! externalsSvnInfo.isValide() )
590 {
591 throw new MojoExecutionException( "Svn info not available for externals dir : "
592 + targetSourceDir );
593 }
594
595 getLog().info( "Svn externals dir is '" + externalsSvnInfo.toString() + "'" );
596
597 externalsEntries = SvnService.loadSvnExternals( basedir,
598 null, targetSourceDir.getAbsolutePath(), getLog() );
599
600
601 getLog().info( "Svn initial externals are '" + externalsEntries.values().toString() + "'" );
602 }
603 Credential credential = Credential.createCredential(
604 dependencySvnUri, username, password, settingsServerId, settings, secDispatcher, getLog() );
605
606 SvnInfo dependencySvnInfo = SvnService.getSvnInfo( basedir, credential, dependencySvnUri,
607 getLog(), false );
608
609 if ( ! dependencySvnInfo.isValide() )
610 {
611 throw new MojoExecutionException( "Svn info not available for dependency : "
612 + dependencyStr + " at " + dependencySvnUri );
613 }
614 getLog().info( "Svn info for dependency : " + dependencyStr + " are " + dependencySvnInfo.toString() );
615
616 SvnExternalEntry ee = buildCurrentDependencyExternalFromPluginsConfig( artifact, dependencyProject,
617 dependencySvnInfo, externalsSvnInfo );
618 if ( null == ee )
619 {
620 ee = buildCurrentDependencyFromDependencyConfig( artifact, dependencyProject,
621 dependencySvnInfo, externalsSvnInfo );
622 }
623 if ( null == ee )
624 {
625 ee = buildCurrentDependencyExternalDefault( artifact, dependencyProject, dependencySvnInfo,
626 externalsSvnInfo );
627 }
628
629 if ( null != ee )
630 {
631 externalsEntries.put( ee );
632 }
633 else
634 {
635 throw new MojoExecutionException( "Unable to build external for : " + dependencyStr );
636 }
637 }
638 else
639 {
640 throw new MojoExecutionException( "SCM unsupported yet : " + scmType[1] );
641 }
642 }
643 if ( null != externalsEntries && null != targetSourceDir )
644 {
645 SvnService.writeSvnExternals( basedir, null, targetSourceDir.getAbsolutePath(),
646 externalsEntries, project.getBuild().getDirectory(), getLog() );
647 }
648 }
649 }