1 package org.apache.maven.continuum.execution.maven.m2;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.continuum.model.repository.LocalRepository;
23 import org.apache.maven.artifact.manager.WagonManager;
24 import org.apache.maven.artifact.repository.ArtifactRepository;
25 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
26 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
27 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
28 import org.apache.maven.continuum.model.project.Project;
29 import org.apache.maven.continuum.model.project.ProjectDependency;
30 import org.apache.maven.continuum.model.project.ProjectDeveloper;
31 import org.apache.maven.continuum.model.project.ProjectNotifier;
32 import org.apache.maven.continuum.project.builder.ContinuumProjectBuildingResult;
33 import org.apache.maven.model.Dependency;
34 import org.apache.maven.model.Developer;
35 import org.apache.maven.model.Extension;
36 import org.apache.maven.model.Model;
37 import org.apache.maven.model.Notifier;
38 import org.apache.maven.model.Plugin;
39 import org.apache.maven.model.Profile;
40 import org.apache.maven.model.ReportPlugin;
41 import org.apache.maven.model.Scm;
42 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
43 import org.apache.maven.profiles.DefaultProfileManager;
44 import org.apache.maven.profiles.ProfileManager;
45 import org.apache.maven.project.InvalidProjectModelException;
46 import org.apache.maven.project.MavenProject;
47 import org.apache.maven.project.MavenProjectBuilder;
48 import org.apache.maven.project.ProjectBuildingException;
49 import org.apache.maven.project.validation.ModelValidationResult;
50 import org.apache.maven.settings.MavenSettingsBuilder;
51 import org.apache.maven.settings.Mirror;
52 import org.apache.maven.settings.Proxy;
53 import org.apache.maven.settings.Server;
54 import org.apache.maven.settings.Settings;
55 import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
56 import org.codehaus.plexus.PlexusConstants;
57 import org.codehaus.plexus.PlexusContainer;
58 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
59 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
60 import org.codehaus.plexus.context.Context;
61 import org.codehaus.plexus.context.ContextException;
62 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable;
63 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
64 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
65 import org.codehaus.plexus.util.StringUtils;
66 import org.codehaus.plexus.util.xml.Xpp3Dom;
67 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 import java.io.File;
72 import java.io.IOException;
73 import java.io.StringWriter;
74 import java.util.ArrayList;
75 import java.util.List;
76
77
78
79
80
81
82
83 public class DefaultMavenBuilderHelper
84 implements MavenBuilderHelper, Contextualizable, Initializable
85 {
86 private static final Logger log = LoggerFactory.getLogger( DefaultMavenBuilderHelper.class );
87
88
89
90
91 private MavenProjectBuilder projectBuilder;
92
93
94
95
96 private ArtifactRepositoryFactory artifactRepositoryFactory;
97
98
99
100
101 private ArtifactRepositoryLayout repositoryLayout;
102
103
104
105
106 private MavenSettingsBuilder mavenSettingsBuilder;
107
108
109
110
111 private String localRepository;
112
113 private PlexusContainer container;
114
115 private LocalRepository repository;
116
117
118
119
120
121 public void mapMetadataToProject( ContinuumProjectBuildingResult result, File metadata, Project continuumProject,
122 boolean update )
123 {
124 MavenProject mavenProject = getMavenProject( result, metadata );
125
126 if ( mavenProject == null )
127 {
128 result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN,
129 "Can't load the maven project. Verify that your scm url is correct and remove/readd the project." );
130 return;
131 }
132
133 mapMavenProjectToContinuumProject( result, mavenProject, continuumProject, update );
134 }
135
136 public void mapMavenProjectToContinuumProject( ContinuumProjectBuildingResult result, MavenProject mavenProject,
137 Project continuumProject, boolean update )
138 {
139 if ( mavenProject == null )
140 {
141 result.addError( ContinuumProjectBuildingResult.ERROR_UNKNOWN, "The maven project is null." );
142 return;
143 }
144
145 if ( update )
146 {
147
148
149
150
151 continuumProject.setName( getProjectName( mavenProject ) );
152
153
154
155
156
157 continuumProject.setVersion( getVersion( mavenProject ) );
158
159
160
161
162
163 continuumProject.setDescription( mavenProject.getDescription() );
164 }
165
166
167
168
169
170
171 if ( StringUtils.isEmpty( continuumProject.getScmUrl() ) )
172 {
173 String scmUrl = getScmUrl( mavenProject );
174
175 continuumProject.setScmUrl( scmUrl );
176
177 if ( !"HEAD".equals( mavenProject.getScm().getTag() ) )
178 {
179 continuumProject.setScmTag( mavenProject.getScm().getTag() );
180 }
181 }
182
183
184
185
186
187 if ( !StringUtils.isEmpty( mavenProject.getGroupId() ) )
188 {
189 continuumProject.setGroupId( mavenProject.getGroupId() );
190 }
191 else
192 {
193 result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_GROUPID );
194 return;
195 }
196
197
198
199
200
201 if ( !StringUtils.isEmpty( mavenProject.getArtifactId() ) )
202 {
203 continuumProject.setArtifactId( mavenProject.getArtifactId() );
204 }
205 else
206 {
207 result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_ARTIFACTID );
208 return;
209 }
210
211
212
213
214
215 if ( !StringUtils.isEmpty( mavenProject.getUrl() ) )
216 {
217 continuumProject.setUrl( mavenProject.getUrl() );
218 }
219
220
221
222
223
224 if ( mavenProject.getDevelopers() != null )
225 {
226 List<ProjectDeveloper> developers = new ArrayList<ProjectDeveloper>();
227
228 for ( Developer d : (List<Developer>) mavenProject.getDevelopers() )
229 {
230 ProjectDeveloper cd = new ProjectDeveloper();
231
232 cd.setScmId( d.getId() );
233
234 cd.setName( d.getName() );
235
236 cd.setEmail( d.getEmail() );
237
238 developers.add( cd );
239 }
240
241 continuumProject.setDevelopers( developers );
242 }
243
244
245
246
247
248 if ( mavenProject.getParent() != null )
249 {
250 MavenProject parentProject = mavenProject.getParent();
251
252 ProjectDependency parent = new ProjectDependency();
253
254 parent.setGroupId( parentProject.getGroupId() );
255
256 parent.setArtifactId( parentProject.getArtifactId() );
257
258 parent.setVersion( parentProject.getVersion() );
259
260 continuumProject.setParent( parent );
261 }
262
263
264
265
266
267 List<ProjectDependency> dependencies = new ArrayList<ProjectDependency>();
268
269 for ( Dependency dependency : (List<Dependency>) mavenProject.getDependencies() )
270 {
271 ProjectDependency cd = new ProjectDependency();
272
273 cd.setGroupId( dependency.getGroupId() );
274
275 cd.setArtifactId( dependency.getArtifactId() );
276
277 cd.setVersion( dependency.getVersion() );
278
279 dependencies.add( cd );
280 }
281
282 for ( Plugin dependency : (List<Plugin>) mavenProject.getBuildPlugins() )
283 {
284 ProjectDependency cd = new ProjectDependency();
285
286 cd.setGroupId( dependency.getGroupId() );
287
288 cd.setArtifactId( dependency.getArtifactId() );
289
290 cd.setVersion( dependency.getVersion() );
291
292 dependencies.add( cd );
293 }
294
295 for ( ReportPlugin dependency : (List<ReportPlugin>) mavenProject.getReportPlugins() )
296 {
297 ProjectDependency cd = new ProjectDependency();
298
299 cd.setGroupId( dependency.getGroupId() );
300
301 cd.setArtifactId( dependency.getArtifactId() );
302
303 cd.setVersion( dependency.getVersion() );
304
305 dependencies.add( cd );
306 }
307
308 for ( Extension dependency : (List<Extension>) mavenProject.getBuildExtensions() )
309 {
310 ProjectDependency cd = new ProjectDependency();
311
312 cd.setGroupId( dependency.getGroupId() );
313
314 cd.setArtifactId( dependency.getArtifactId() );
315
316 cd.setVersion( dependency.getVersion() );
317
318 dependencies.add( cd );
319 }
320
321 continuumProject.setDependencies( dependencies );
322
323
324
325
326
327 List<ProjectNotifier> userNotifiers = new ArrayList<ProjectNotifier>();
328
329 if ( continuumProject.getNotifiers() != null )
330 {
331 for ( int i = 0; i < continuumProject.getNotifiers().size(); i++ )
332 {
333 ProjectNotifier notifier = (ProjectNotifier) continuumProject.getNotifiers().get( i );
334
335 if ( notifier.isFromUser() )
336 {
337 ProjectNotifier userNotifier = new ProjectNotifier();
338
339 userNotifier.setType( notifier.getType() );
340
341 userNotifier.setEnabled( notifier.isEnabled() );
342
343 userNotifier.setConfiguration( notifier.getConfiguration() );
344
345 userNotifier.setFrom( notifier.getFrom() );
346
347 userNotifier.setRecipientType( notifier.getRecipientType() );
348
349 userNotifier.setSendOnError( notifier.isSendOnError() );
350
351 userNotifier.setSendOnFailure( notifier.isSendOnFailure() );
352
353 userNotifier.setSendOnSuccess( notifier.isSendOnSuccess() );
354
355 userNotifier.setSendOnWarning( notifier.isSendOnWarning() );
356
357 userNotifier.setSendOnScmFailure( notifier.isSendOnScmFailure() );
358
359 userNotifiers.add( userNotifier );
360 }
361 }
362 }
363
364 List<ProjectNotifier> notifiers = getNotifiers( result, mavenProject );
365 if ( notifiers != null )
366 {
367 continuumProject.setNotifiers( notifiers );
368 }
369
370 for ( ProjectNotifier notifier : userNotifiers )
371 {
372 continuumProject.addNotifier( notifier );
373 }
374 }
375
376 public MavenProject getMavenProject( ContinuumProjectBuildingResult result, File file )
377 {
378 MavenProject project;
379
380 try
381 {
382
383
384
385 Settings settings = getSettings();
386
387 if ( log.isDebugEnabled() )
388 {
389 writeSettings( settings );
390 }
391
392 ProfileManager profileManager = new DefaultProfileManager( container, settings );
393
394 project = projectBuilder.build( file, getLocalRepository(), profileManager, true );
395
396 if ( log.isDebugEnabled() )
397 {
398 writePom( project );
399 writeActiveProfileStatement( project );
400 }
401
402 }
403 catch ( ProjectBuildingException e )
404 {
405 StringBuffer messages = new StringBuffer();
406
407 Throwable cause = e.getCause();
408
409 if ( cause != null )
410 {
411 while ( ( cause.getCause() != null ) && ( cause instanceof ProjectBuildingException ) )
412 {
413 cause = cause.getCause();
414 }
415 }
416
417 if ( e instanceof InvalidProjectModelException )
418 {
419 InvalidProjectModelException ex = (InvalidProjectModelException) e;
420
421 ModelValidationResult validationResult = ex.getValidationResult();
422
423 if ( validationResult != null && validationResult.getMessageCount() > 0 )
424 {
425 for ( String valmsg : (List<String>) validationResult.getMessages() )
426 {
427 result.addError( ContinuumProjectBuildingResult.ERROR_VALIDATION, valmsg );
428 messages.append( valmsg );
429 messages.append( "\n" );
430 }
431 }
432 }
433
434 if ( cause instanceof ArtifactNotFoundException )
435 {
436 result.addError( ContinuumProjectBuildingResult.ERROR_ARTIFACT_NOT_FOUND, ( cause ).toString() );
437 return null;
438 }
439
440 result.addError( ContinuumProjectBuildingResult.ERROR_PROJECT_BUILDING, e.getMessage() );
441
442 String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").\n" + messages;
443
444 file.delete();
445
446 log.error( msg );
447
448 return null;
449 }
450
451 catch ( Exception e )
452 {
453 result.addError( ContinuumProjectBuildingResult.ERROR_PROJECT_BUILDING, e.getMessage() );
454
455 String msg = "Cannot build maven project from " + file + " (" + e.getMessage() + ").";
456
457 file.delete();
458
459 log.error( msg );
460
461 return null;
462 }
463
464
465
466
467
468
469 Scm scm = project.getScm();
470
471 if ( scm == null )
472 {
473 result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM, getProjectName( project ) );
474
475 log.error( "Missing 'scm' element in the " + getProjectName( project ) + " POM." );
476
477 return null;
478 }
479
480 String url = scm.getConnection();
481
482 if ( StringUtils.isEmpty( url ) )
483 {
484 result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_SCM_CONNECTION, getProjectName( project ) );
485
486 log.error( "Missing 'connection' element in the 'scm' element in the " + getProjectName( project ) +
487 " POM." );
488
489 return null;
490 }
491
492 return project;
493 }
494
495 public ArtifactRepository getLocalRepository()
496 throws SettingsConfigurationException
497 {
498 return getRepository( getSettings() );
499 }
500
501
502
503
504
505 public String getProjectName( MavenProject project )
506 {
507 String name = project.getName();
508
509 if ( StringUtils.isEmpty( name ) )
510 {
511 return project.getId();
512 }
513
514 return name;
515 }
516
517 private String getScmUrl( MavenProject project )
518 {
519 return project.getScm().getConnection();
520 }
521
522 private List<ProjectNotifier> getNotifiers( ContinuumProjectBuildingResult result, MavenProject mavenProject )
523 {
524 List<ProjectNotifier> notifiers = new ArrayList<ProjectNotifier>();
525
526 if ( mavenProject.getCiManagement() != null && mavenProject.getCiManagement().getNotifiers() != null )
527 {
528 for ( Notifier projectNotifier : (List<Notifier>) mavenProject.getCiManagement().getNotifiers() )
529 {
530 ProjectNotifier notifier = new ProjectNotifier();
531
532 if ( StringUtils.isEmpty( projectNotifier.getType() ) )
533 {
534 result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_NOTIFIER_TYPE );
535 return null;
536 }
537
538 notifier.setType( projectNotifier.getType() );
539
540 if ( projectNotifier.getConfiguration() == null )
541 {
542 result.addError( ContinuumProjectBuildingResult.ERROR_MISSING_NOTIFIER_CONFIGURATION );
543 return null;
544 }
545
546 notifier.setConfiguration( projectNotifier.getConfiguration() );
547
548 notifier.setFrom( ProjectNotifier.FROM_PROJECT );
549
550 notifier.setSendOnSuccess( projectNotifier.isSendOnSuccess() );
551
552 notifier.setSendOnFailure( projectNotifier.isSendOnFailure() );
553
554 notifier.setSendOnError( projectNotifier.isSendOnError() );
555
556 notifier.setSendOnWarning( projectNotifier.isSendOnWarning() );
557
558 notifier.setSendOnScmFailure( false );
559
560 notifiers.add( notifier );
561 }
562 }
563
564 return notifiers;
565 }
566
567 private String getVersion( MavenProject project )
568 {
569 return project.getVersion();
570 }
571
572
573
574
575
576 private Settings getSettings()
577 throws SettingsConfigurationException
578 {
579 try
580 {
581 return mavenSettingsBuilder.buildSettings( false );
582 }
583 catch ( IOException e )
584 {
585 throw new SettingsConfigurationException( "Error reading settings file", e );
586 }
587 catch ( XmlPullParserException e )
588 {
589 throw new SettingsConfigurationException( e.getMessage(), e.getDetail(), e.getLineNumber(),
590 e.getColumnNumber() );
591 }
592 }
593
594 private ArtifactRepository getRepository( Settings settings )
595 {
596
597
598
599
600
601 String localRepo = localRepository;
602
603 if ( repository != null )
604 {
605 return artifactRepositoryFactory.createArtifactRepository( repository.getName(),
606 "file://" + repository.getLocation(),
607 repositoryLayout, null, null );
608 }
609 else if ( !( StringUtils.isEmpty( settings.getLocalRepository() ) ) )
610 {
611 localRepo = settings.getLocalRepository();
612 }
613
614 return artifactRepositoryFactory.createArtifactRepository( "local", "file://" + localRepo, repositoryLayout,
615 null, null );
616 }
617
618 private void writeSettings( Settings settings )
619 {
620 StringWriter sWriter = new StringWriter();
621
622 SettingsXpp3Writer settingsWriter = new SettingsXpp3Writer();
623
624 try
625 {
626 settingsWriter.write( sWriter, settings );
627
628 StringBuffer message = new StringBuffer();
629
630 message.append( "\n************************************************************************************" );
631 message.append( "\nEffective Settings" );
632 message.append( "\n************************************************************************************" );
633 message.append( "\n" );
634 message.append( sWriter.toString() );
635 message.append( "\n************************************************************************************" );
636 message.append( "\n\n" );
637
638 log.debug( message.toString() );
639 }
640 catch ( IOException e )
641 {
642 log.warn( "Cannot serialize Settings to XML.", e );
643 }
644 }
645
646 private void writePom( MavenProject project )
647 {
648 StringBuffer message = new StringBuffer();
649
650 Model pom = project.getModel();
651
652 StringWriter sWriter = new StringWriter();
653
654 MavenXpp3Writer pomWriter = new MavenXpp3Writer();
655
656 try
657 {
658 pomWriter.write( sWriter, pom );
659
660 message.append( "\n************************************************************************************" );
661 message.append( "\nEffective POM for project \'" ).append( project.getId() ).append( "\'" );
662 message.append( "\n************************************************************************************" );
663 message.append( "\n" );
664 message.append( sWriter.toString() );
665 message.append( "\n************************************************************************************" );
666 message.append( "\n\n" );
667
668 log.debug( message.toString() );
669 }
670 catch ( IOException e )
671 {
672 log.warn( "Cannot serialize POM to XML.", e );
673 }
674 }
675
676 private void writeActiveProfileStatement( MavenProject project )
677 {
678 List<Profile> profiles = project.getActiveProfiles();
679
680 StringBuffer message = new StringBuffer();
681
682 message.append( "\n" );
683
684 message.append( "\n************************************************************************************" );
685 message.append( "\nActive Profiles for Project \'" ).append( project.getId() ).append( "\'" );
686 message.append( "\n************************************************************************************" );
687 message.append( "\n" );
688
689 if ( profiles == null || profiles.isEmpty() )
690 {
691 message.append( "There are no active profiles." );
692 }
693 else
694 {
695 message.append( "The following profiles are active:\n" );
696
697 for ( Profile profile : profiles )
698 {
699 message.append( "\n - " ).append( profile.getId() ).append( " (source: " ).append(
700 profile.getSource() ).append( ")" );
701 }
702
703 }
704
705 message.append( "\n************************************************************************************" );
706 message.append( "\n\n" );
707
708 log.debug( message.toString() );
709 }
710
711
712
713
714
715
716
717 private void resolveParameters( Settings settings )
718 throws ComponentLookupException, ComponentLifecycleException, SettingsConfigurationException
719 {
720 WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
721
722 try
723 {
724 Proxy proxy = settings.getActiveProxy();
725
726 if ( proxy != null )
727 {
728 if ( proxy.getHost() == null )
729 {
730 throw new SettingsConfigurationException( "Proxy in settings.xml has no host" );
731 }
732
733 wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(),
734 proxy.getPassword(), proxy.getNonProxyHosts() );
735 }
736
737 for ( Server server : (List<Server>) settings.getServers() )
738 {
739 wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), server.getPassword(),
740 server.getPrivateKey(), server.getPassphrase() );
741
742 wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(),
743 server.getDirectoryPermissions() );
744
745 if ( server.getConfiguration() != null )
746 {
747 wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() );
748 }
749 }
750
751 for ( Mirror mirror : (List<Mirror>) settings.getMirrors() )
752 {
753 wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
754 }
755 }
756 finally
757 {
758 container.release( wagonManager );
759 }
760 }
761
762
763
764
765
766 public void contextualize( Context context )
767 throws ContextException
768 {
769 container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
770 }
771
772 public void initialize()
773 throws InitializationException
774 {
775 try
776 {
777 Settings settings = getSettings();
778
779 resolveParameters( settings );
780 }
781 catch ( Exception e )
782 {
783 throw new InitializationException( "Can't initialize '" + getClass().getName() + "'", e );
784 }
785 }
786
787 public void setLocalRepository( LocalRepository repository )
788 {
789 this.repository = repository;
790 }
791 }