1 package org.apache.maven.continuum.web.action;
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.configuration.BuildAgentConfigurationException;
23 import org.apache.continuum.release.distributed.DistributedReleaseUtil;
24 import org.apache.continuum.release.distributed.manager.DistributedReleaseManager;
25 import org.apache.continuum.web.action.AbstractReleaseAction;
26 import org.apache.continuum.web.util.AuditLog;
27 import org.apache.continuum.web.util.AuditLogConstants;
28 import org.apache.maven.continuum.ContinuumException;
29 import org.apache.maven.continuum.installation.InstallationService;
30 import org.apache.maven.continuum.model.project.Project;
31 import org.apache.maven.continuum.model.system.Profile;
32 import org.apache.maven.continuum.release.ContinuumReleaseManager;
33 import org.apache.maven.continuum.release.ContinuumReleaseManagerListener;
34 import org.apache.maven.continuum.release.DefaultReleaseManagerListener;
35 import org.apache.maven.continuum.web.exception.AuthorizationRequiredException;
36 import org.apache.maven.continuum.web.model.ReleaseListenerSummary;
37 import org.apache.maven.model.Model;
38 import org.apache.maven.model.Plugin;
39 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
40 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
41 import org.apache.maven.shared.release.ReleaseResult;
42 import org.apache.maven.shared.release.versions.DefaultVersionInfo;
43 import org.apache.maven.shared.release.versions.VersionInfo;
44 import org.codehaus.plexus.util.StringUtils;
45 import org.codehaus.plexus.util.xml.Xpp3Dom;
46
47 import java.io.File;
48 import java.io.FileReader;
49 import java.util.ArrayList;
50 import java.util.HashMap;
51 import java.util.Iterator;
52 import java.util.List;
53 import java.util.Map;
54 import java.util.Properties;
55
56
57
58
59
60
61 public class ReleasePrepareAction
62 extends AbstractReleaseAction
63 {
64 private static final String SCM_SVN_PROTOCOL_PREFIX = "scm:svn";
65
66 private static final String SNAPSHOT_VERSION_SUFFIX = "-SNAPSHOT";
67
68 private int projectId;
69
70 private String releaseId;
71
72 private String name;
73
74 private String scmUsername;
75
76 private String scmPassword;
77
78 private String scmTag;
79
80 private String scmTagBase;
81
82 private String scmCommentPrefix;
83
84 private boolean scmUseEditMode = false;
85
86 private List<Map<String, String>> projects = new ArrayList<Map<String, String>>();
87
88 private List<String> projectKeys;
89
90 private List<String> devVersions;
91
92 private List<String> relVersions;
93
94 private String prepareGoals;
95
96 private String arguments;
97
98 private ReleaseResult result;
99
100 private ContinuumReleaseManagerListener listener;
101
102 private String projectGroupName = "";
103
104 private List<Profile> profiles;
105
106 private int profileId;
107
108 private boolean autoVersionSubmodules = false;
109
110 private boolean addSchema = true;
111
112 private ReleaseListenerSummary listenerSummary;
113
114 public String input()
115 throws Exception
116 {
117 try
118 {
119 checkBuildProjectInGroupAuthorization( getProjectGroupName() );
120 }
121 catch ( AuthorizationRequiredException e )
122 {
123 return REQUIRES_AUTHORIZATION;
124 }
125
126 Project project = getContinuum().getProject( projectId );
127 scmUsername = project.getScmUsername();
128 scmPassword = project.getScmPassword();
129 scmTag = project.getScmTag();
130
131 if ( scmTag == null )
132 {
133 String version = project.getVersion();
134 int idx = version.indexOf( SNAPSHOT_VERSION_SUFFIX );
135
136 if ( idx >= 0 )
137 {
138
139 scmTag = project.getArtifactId() + "-" + version.substring( 0, idx );
140 }
141 else
142 {
143 scmTag = project.getArtifactId() + "-" + version;
144 }
145 }
146
147 String scmUrl = project.getScmUrl();
148 if ( scmUrl.startsWith( SCM_SVN_PROTOCOL_PREFIX ) )
149 {
150 scmTagBase = new SvnScmProviderRepository( scmUrl, scmUsername, scmPassword ).getTagBase();
151
152 scmTagBase = scmTagBase.substring( SCM_SVN_PROTOCOL_PREFIX.length() + 1 );
153 }
154 else
155 {
156 scmTagBase = "";
157 }
158
159 ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
160
161
162 releaseManager.sanitizeTagName( scmUrl, scmTag );
163
164 prepareGoals = "clean integration-test";
165
166 if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
167 {
168 DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
169
170 try
171 {
172 getReleasePluginParameters( distributedReleaseManager.getReleasePluginParameters( projectId, "pom.xml" ) );
173
174 projects = distributedReleaseManager.processProject( projectId, "pom.xml", autoVersionSubmodules );
175 }
176 catch ( BuildAgentConfigurationException e )
177 {
178 List<String> args = new ArrayList<String>();
179 args.add( e.getMessage() );
180
181 addActionError( getText( "distributedBuild.releasePrepare.input.error", args ) );
182 return ERROR;
183 }
184 }
185 else
186 {
187 try
188 {
189 String workingDirectory = getContinuum().getWorkingDirectory( project.getId() ).getPath();
190
191 getReleasePluginParameters( workingDirectory, "pom.xml" );
192
193 processProject( workingDirectory, "pom.xml" );
194 }
195 catch ( Exception e )
196 {
197 List<String> args = new ArrayList<String>();
198 args.add( e.getMessage() );
199
200 addActionError( getText( "releasePrepare.input.error", args ) );
201 return ERROR;
202 }
203 }
204
205 profiles = this.getContinuum().getProfileService().getAllProfiles();
206
207 return SUCCESS;
208 }
209
210 private void getReleasePluginParameters( String workingDirectory, String pomFilename )
211 throws Exception
212 {
213
214 MavenXpp3Reader pomReader = new MavenXpp3Reader();
215 Model model = pomReader.read( new FileReader( new File( workingDirectory, pomFilename ) ) );
216
217 if ( model.getBuild() != null && model.getBuild().getPlugins() != null )
218 {
219 for ( Plugin plugin : (List<Plugin>) model.getBuild().getPlugins() )
220 {
221 if ( plugin.getGroupId() != null && plugin.getGroupId().equals( "org.apache.maven.plugins" ) &&
222 plugin.getArtifactId() != null && plugin.getArtifactId().equals( "maven-release-plugin" ) )
223 {
224 Xpp3Dom dom = (Xpp3Dom) plugin.getConfiguration();
225
226 if ( dom != null )
227 {
228 Xpp3Dom configuration = dom.getChild( "releaseLabel" );
229 if ( configuration != null )
230 {
231 scmTag = configuration.getValue();
232 }
233
234 configuration = dom.getChild( "tag" );
235 if ( configuration != null )
236 {
237 scmTag = configuration.getValue();
238 }
239
240 configuration = dom.getChild( "tagBase" );
241 if ( configuration != null )
242 {
243 scmTagBase = configuration.getValue();
244 }
245
246 configuration = dom.getChild( "preparationGoals" );
247 if ( configuration != null )
248 {
249 prepareGoals = configuration.getValue();
250 }
251
252 configuration = dom.getChild( "arguments" );
253 if ( configuration != null )
254 {
255 arguments = configuration.getValue();
256 }
257
258 configuration = dom.getChild( "scmCommentPrefix" );
259 if ( configuration != null )
260 {
261 scmCommentPrefix = configuration.getValue();
262 }
263
264 configuration = dom.getChild( "autoVersionSubmodules" );
265 if ( configuration != null )
266 {
267 autoVersionSubmodules = Boolean.valueOf( configuration.getValue() );
268 }
269
270 configuration = dom.getChild( "addSchema" );
271 if ( configuration != null )
272 {
273 addSchema = Boolean.valueOf( configuration.getValue() );
274 }
275 }
276 }
277 }
278 }
279 }
280
281 public String execute()
282 throws Exception
283 {
284 try
285 {
286 checkBuildProjectInGroupAuthorization( getProjectGroupName() );
287 }
288 catch ( AuthorizationRequiredException e )
289 {
290 return REQUIRES_AUTHORIZATION;
291 }
292
293 Project project = getContinuum().getProject( projectId );
294
295 name = project.getName();
296 if ( name == null )
297 {
298 name = project.getArtifactId();
299 }
300
301 Profile profile = null;
302
303 if ( profileId != -1 )
304 {
305 profile = getContinuum().getProfileService().getProfile( profileId );
306 }
307
308 Map<String, String> environments = getEnvironments( profile );
309
310 if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
311 {
312 DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
313
314 try
315 {
316 releaseId = distributedReleaseManager.releasePrepare( project, getReleaseProperties(), getRelVersionMap(), getDevVersionMap(),
317 environments );
318
319 if ( releaseId == null )
320 {
321 addActionError( "Failed to release project" );
322 return ERROR;
323 }
324 }
325 catch ( BuildAgentConfigurationException e )
326 {
327 List<String> args = new ArrayList<String>();
328 args.add( e.getMessage() );
329
330 addActionError( getText( "distributedBuild.releasePrepare.release.error", args ) );
331 return ERROR;
332 }
333 }
334 else
335 {
336 listener = new DefaultReleaseManagerListener();
337
338 String workingDirectory = getContinuum().getWorkingDirectory( projectId ).getPath();
339
340 ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
341
342 String executable = getContinuum().getInstallationService()
343 .getExecutorConfigurator( InstallationService.MAVEN2_TYPE ).getExecutable();
344
345 if ( environments != null )
346 {
347 String m2Home = environments.get( getContinuum().getInstallationService().getEnvVar( InstallationService.MAVEN2_TYPE ) );
348 if ( StringUtils.isNotEmpty( m2Home ) )
349 {
350 executable = m2Home + File.separator + "bin" + File.separator + executable;
351 }
352 }
353
354 releaseId =
355 releaseManager.prepare( project, getReleaseProperties(), getRelVersionMap(), getDevVersionMap(), listener,
356 workingDirectory, environments, executable );
357 }
358
359 AuditLog event = new AuditLog( "Release id=" + releaseId, AuditLogConstants.PREPARE_RELEASE );
360 event.setCategory( AuditLogConstants.PROJECT );
361 event.setCurrentUser( getPrincipal() );
362 event.log();
363
364 return SUCCESS;
365 }
366
367 public String viewResult()
368 throws Exception
369 {
370 try
371 {
372 checkBuildProjectInGroupAuthorization( getProjectGroupName() );
373 }
374 catch ( AuthorizationRequiredException e )
375 {
376 return REQUIRES_AUTHORIZATION;
377 }
378
379 if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
380 {
381 DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
382
383 try
384 {
385 result = distributedReleaseManager.getReleaseResult( releaseId );
386 }
387 catch ( BuildAgentConfigurationException e )
388 {
389 addActionError( "release" );
390 return "viewResultError";
391 }
392 }
393 else
394 {
395 result = (ReleaseResult) getContinuum().getReleaseManager().getReleaseResults().get( releaseId );
396 }
397
398 return "viewResult";
399 }
400
401 public String checkProgress()
402 throws Exception
403 {
404 try
405 {
406 checkBuildProjectInGroupAuthorization( getProjectGroupName() );
407 }
408 catch ( AuthorizationRequiredException e )
409 {
410 return REQUIRES_AUTHORIZATION;
411 }
412
413 String status;
414
415 listenerSummary = new ReleaseListenerSummary();
416
417 if ( getContinuum().getConfiguration().isDistributedBuildEnabled() )
418 {
419 DistributedReleaseManager distributedReleaseManager = getContinuum().getDistributedReleaseManager();
420 Map listenerMap;
421 try
422 {
423 listenerMap = distributedReleaseManager.getListener( releaseId );
424 }
425 catch ( BuildAgentConfigurationException e )
426 {
427 addActionError( "" );
428 return "";
429 }
430
431 if ( listenerMap != null && !listenerMap.isEmpty() )
432 {
433 int state = DistributedReleaseUtil.getReleaseState( listenerMap );
434
435 if ( state == ContinuumReleaseManagerListener.FINISHED )
436 {
437 distributedReleaseManager.removeListener( releaseId );
438
439 result = distributedReleaseManager.getReleaseResult( releaseId );
440
441 status = "finished";
442 }
443 else
444 {
445 status = "inProgress";
446 }
447
448 listenerSummary.setPhases( DistributedReleaseUtil.getReleasePhases( listenerMap ) );
449 listenerSummary.setCompletedPhases( DistributedReleaseUtil.getCompletedReleasePhases( listenerMap ) );
450 listenerSummary.setInProgress( DistributedReleaseUtil.getReleaseInProgress( listenerMap ) );
451 listenerSummary.setError( DistributedReleaseUtil.getReleaseError( listenerMap ) );
452 }
453 else
454 {
455 throw new Exception( "There is no release on-going or finished with id: " + releaseId );
456 }
457 }
458 else
459 {
460 ContinuumReleaseManager releaseManager = getContinuum().getReleaseManager();
461
462 listener = (ContinuumReleaseManagerListener) releaseManager.getListeners().get( releaseId );
463
464 if ( listener != null )
465 {
466 if ( listener.getState() == ContinuumReleaseManagerListener.FINISHED )
467 {
468 releaseManager.getListeners().remove( releaseId );
469
470 result = (ReleaseResult) releaseManager.getReleaseResults().get( releaseId );
471
472 status = "finished";
473 }
474 else
475 {
476 status = "inProgress";
477 }
478
479 listenerSummary.setPhases( listener.getPhases() );
480 listenerSummary.setCompletedPhases( listener.getCompletedPhases() );
481 listenerSummary.setInProgress( listener.getInProgress() );
482 listenerSummary.setError( listener.getError() );
483 }
484 else
485 {
486 throw new Exception( "There is no release on-going or finished with id: " + releaseId );
487 }
488 }
489
490 return status;
491 }
492
493 private void processProject( String workingDirectory, String pomFilename )
494 throws Exception
495 {
496 MavenXpp3Reader pomReader = new MavenXpp3Reader();
497 Model model = pomReader.read( new FileReader( new File( workingDirectory, pomFilename ) ) );
498
499 if ( model.getGroupId() == null )
500 {
501 model.setGroupId( model.getParent().getGroupId() );
502 }
503
504 if ( model.getVersion() == null )
505 {
506 model.setVersion( model.getParent().getVersion() );
507 }
508
509 setProperties( model );
510
511 if ( !autoVersionSubmodules )
512 {
513 for ( Iterator modules = model.getModules().iterator(); modules.hasNext(); )
514 {
515 processProject( workingDirectory + "/" + modules.next().toString(), "pom.xml" );
516 }
517 }
518 }
519
520 private void setProperties( Model model )
521 throws Exception
522 {
523 Map<String, String> params = new HashMap<String, String>();
524
525 params.put( "key", model.getGroupId() + ":" + model.getArtifactId() );
526
527 if ( model.getName() == null )
528 {
529 model.setName( model.getArtifactId() );
530 }
531 params.put( "name", model.getName() );
532
533 VersionInfo version = new DefaultVersionInfo( model.getVersion() );
534
535 params.put( "release", version.getReleaseVersionString() );
536 params.put( "dev", version.getNextVersion().getSnapshotVersionString() );
537
538 projects.add( params );
539 }
540
541 private Map<String, String> getDevVersionMap()
542 {
543 return getVersionMap( projectKeys, devVersions );
544 }
545
546 private Map<String, String> getRelVersionMap()
547 {
548 return getVersionMap( projectKeys, relVersions );
549 }
550
551 private Map<String, String> getVersionMap( List<String> keys, List<String> versions )
552 {
553 Map<String, String> versionMap = new HashMap<String, String>();
554
555 for ( int idx = 0; idx < keys.size(); idx++ )
556 {
557 String key = keys.get( idx );
558 String version;
559 if ( !autoVersionSubmodules )
560 {
561 version = versions.get( idx );
562 }
563 else
564 {
565 version = versions.get( 0 );
566 }
567
568 versionMap.put( key, version );
569 }
570
571 return versionMap;
572 }
573
574 private Properties getReleaseProperties()
575 {
576 Properties p = new Properties();
577
578 if ( StringUtils.isNotEmpty( scmUsername ) )
579 {
580 p.setProperty( "username", scmUsername );
581 }
582
583 if ( StringUtils.isNotEmpty( scmPassword ) )
584 {
585 p.setProperty( "password", scmPassword );
586 }
587
588 if ( StringUtils.isNotEmpty( scmTagBase ) )
589 {
590 p.setProperty( "tagBase", scmTagBase );
591 }
592
593 if ( StringUtils.isNotEmpty( scmCommentPrefix ) )
594 {
595 p.setProperty( "commentPrefix", scmCommentPrefix );
596 }
597
598 p.setProperty( "tag", scmTag );
599 p.setProperty( "prepareGoals", prepareGoals );
600 p.setProperty( "arguments", arguments );
601 p.setProperty( "useEditMode", Boolean.toString( scmUseEditMode ) );
602 p.setProperty( "addSchema", Boolean.toString( addSchema ) );
603 p.setProperty( "autoVersionSubmodules", Boolean.toString( autoVersionSubmodules ) );
604
605 return p;
606 }
607
608 private void getReleasePluginParameters( Map context )
609 {
610 scmTag = DistributedReleaseUtil.getScmTag( context, scmTag );
611
612 scmTagBase = DistributedReleaseUtil.getScmTagBase( context, scmTagBase );
613
614 prepareGoals = DistributedReleaseUtil.getPrepareGoals( context, prepareGoals );
615
616 arguments = DistributedReleaseUtil.getArguments( context, "" );
617
618 scmCommentPrefix = DistributedReleaseUtil.getScmCommentPrefix( context, "" );
619
620 autoVersionSubmodules = DistributedReleaseUtil.getAutoVersionSubmodules( context, false );
621
622 addSchema = DistributedReleaseUtil.getAddSchema( context, true );
623 }
624
625 public List<String> getProjectKeys()
626 {
627 return projectKeys;
628 }
629
630 public void setProjectKeys( List<String> projectKeys )
631 {
632 this.projectKeys = projectKeys;
633 }
634
635 public List<String> getDevVersions()
636 {
637 return devVersions;
638 }
639
640 public void setDevVersions( List<String> devVersions )
641 {
642 this.devVersions = devVersions;
643 }
644
645 public List<String> getRelVersions()
646 {
647 return relVersions;
648 }
649
650 public void setRelVersions( List<String> relVersions )
651 {
652 this.relVersions = relVersions;
653 }
654
655 public int getProjectId()
656 {
657 return projectId;
658 }
659
660 public void setProjectId( int projectId )
661 {
662 this.projectId = projectId;
663 }
664
665 public String getScmUsername()
666 {
667 return scmUsername;
668 }
669
670 public void setScmUsername( String scmUsername )
671 {
672 this.scmUsername = scmUsername;
673 }
674
675 public String getScmPassword()
676 {
677 return scmPassword;
678 }
679
680 public void setScmPassword( String scmPassword )
681 {
682 this.scmPassword = scmPassword;
683 }
684
685 public String getScmTag()
686 {
687 return scmTag;
688 }
689
690 public void setScmTag( String scmTag )
691 {
692 this.scmTag = scmTag;
693 }
694
695 public String getScmTagBase()
696 {
697 return scmTagBase;
698 }
699
700 public void setScmTagBase( String scmTagBase )
701 {
702 this.scmTagBase = scmTagBase;
703 }
704
705 public List<Map<String, String>> getProjects()
706 {
707 return projects;
708 }
709
710 public void setProjects( List<Map<String, String>> projects )
711 {
712 this.projects = projects;
713 }
714
715 public ContinuumReleaseManagerListener getListener()
716 {
717 return listener;
718 }
719
720 public void setListener( DefaultReleaseManagerListener listener )
721 {
722 this.listener = listener;
723 }
724
725 public String getName()
726 {
727 return name;
728 }
729
730 public void setName( String name )
731 {
732 this.name = name;
733 }
734
735 public String getReleaseId()
736 {
737 return releaseId;
738 }
739
740 public void setReleaseId( String releaseId )
741 {
742 this.releaseId = releaseId;
743 }
744
745 public ReleaseResult getResult()
746 {
747 return result;
748 }
749
750 public void setResult( ReleaseResult result )
751 {
752 this.result = result;
753 }
754
755 public String getPrepareGoals()
756 {
757 return prepareGoals;
758 }
759
760 public void setPrepareGoals( String prepareGoals )
761 {
762 this.prepareGoals = prepareGoals;
763 }
764
765 public String getArguments()
766 {
767 return arguments;
768 }
769
770 public void setArguments( String arguments )
771 {
772 this.arguments = arguments;
773 }
774
775 public void validate()
776 {
777 }
778
779 public String getProjectGroupName()
780 throws ContinuumException
781 {
782 if ( StringUtils.isEmpty( projectGroupName ) )
783 {
784 projectGroupName = getContinuum().getProjectGroupByProjectId( projectId ).getName();
785 }
786
787 return projectGroupName;
788 }
789
790 public List<Profile> getProfiles()
791 {
792 return profiles;
793 }
794
795 public void setProfiles( List<Profile> profiles )
796 {
797 this.profiles = profiles;
798 }
799
800 public int getProfileId()
801 {
802 return profileId;
803 }
804
805 public void setProfileId( int profileId )
806 {
807 this.profileId = profileId;
808 }
809
810 public boolean isScmUseEditMode()
811 {
812 return scmUseEditMode;
813 }
814
815 public void setScmUseEditMode( boolean scmUseEditMode )
816 {
817 this.scmUseEditMode = scmUseEditMode;
818 }
819
820 public String getScmCommentPrefix()
821 {
822 return scmCommentPrefix;
823 }
824
825 public void setScmCommentPrefix( String scmCommentPrefix )
826 {
827 this.scmCommentPrefix = scmCommentPrefix;
828 }
829
830 public boolean isAutoVersionSubmodules()
831 {
832 return autoVersionSubmodules;
833 }
834
835 public void setAutoVersionSubmodules( boolean autoVersionSubmodules )
836 {
837 this.autoVersionSubmodules = autoVersionSubmodules;
838 }
839
840 public boolean isAddSchema()
841 {
842 return addSchema;
843 }
844
845 public void setAddSchema( boolean addSchema )
846 {
847 this.addSchema = addSchema;
848 }
849
850 public ReleaseListenerSummary getListenerSummary()
851 {
852 return listenerSummary;
853 }
854
855 public void setListenerSummary( ReleaseListenerSummary listenerSummary )
856 {
857 this.listenerSummary = listenerSummary;
858 }
859 }