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