View Javadoc

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