View Javadoc
1   package org.apache.maven.plugin.cxx.utils.release;
2   
3   /*
4    * Copyright (C) 2011-2016, Neticoa SAS France - Tous droits réservés.
5    * Author(s) : Franck Bonin, Neticoa SAS France
6    *
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   *
19   */
20  
21  import java.util.List;
22  import java.util.ArrayList;
23  import java.io.File;
24  import java.nio.file.Path;
25  import java.net.URL;
26  import java.net.MalformedURLException;
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugin.MojoFailureException;
29  import org.apache.maven.project.MavenProject;
30  import org.apache.maven.shared.release.env.ReleaseEnvironment;
31  import org.apache.maven.shared.release.ReleaseResult;
32  import org.apache.maven.shared.release.util.ReleaseUtil;
33  import org.codehaus.plexus.util.StringUtils;
34  import org.apache.maven.plugin.cxx.utils.Credential;
35  import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
36  import org.apache.maven.scm.provider.ScmUrlUtils;
37  import org.apache.maven.plugin.cxx.utils.svn.SvnService;
38  import org.apache.maven.plugin.cxx.utils.svn.SvnInfo;
39  import org.apache.maven.artifact.ArtifactUtils;
40  
41  /**
42   * 
43   * @author Franck Bonin
44   * 
45   * @plexus.component role="org.apache.maven.plugin.cxx.utils.release.CxxReleasePhase" role-hint="PreCheckPomPhase"
46   */
47  public class PreCheckPomPhase
48      extends CxxAbstractMavenReleasePluginPhase
49  {
50     
51      /**
52       * The decrypter for passwords.
53       * 
54       * When this plugin requires Maven 3.0 as minimum, this component can be removed and o.a.m.s.c.SettingsDecrypter be
55       * used instead.
56       * component loaded with plexus, see components.xml
57       */
58      private SecDispatcher secDispatcher;
59     
60      @Override
61      public ReleaseResult run( CxxReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
62                           List<MavenProject> reactorProjects )
63          throws MojoExecutionException, MojoFailureException
64      {
65          // checkPomPhase may fillup an empty scmId, prevent it !
66          String previousScmId = releaseDescriptor.getScmId();
67          
68          ReleaseResult result = super.run( releaseDescriptor, releaseEnvironment,  reactorProjects );
69          
70          // restore scmId, if empty
71          if ( StringUtils.isEmpty( releaseDescriptor.getScmId() ) )
72          {
73              releaseDescriptor.setScmId( previousScmId );
74          }
75          
76          /*for ( MavenProject project : reactorProjects )
77          {
78              if ( ArtifactUtils.isSnapshot( project.getVersion() ) )
79              {
80                  logInfo( result, "is Snapshot = " + ArtifactUtils.versionlessKey( project.getArtifact() ) );
81              }
82              else
83              {
84                  logInfo( result, "is not a Snapshot = " + ArtifactUtils.versionlessKey( project.getArtifact() ) );
85              }
86          }*/        
87          
88          logInfo( result, "SCM URL selected : " + releaseDescriptor.getScmSourceUrl() );
89          
90          //1/ resolve scm credential !
91          Credential credential = Credential.createCredential(
92                      ScmUrlUtils.getProviderSpecificPart( releaseDescriptor.getScmSourceUrl() ),
93              /*use org.apache.maven.scm.provider.ScmUrlUtils from maven-scm-api artifact
94              to extract uri from releaseDescriptor.getScmSourceUrl(),*/
95                      releaseDescriptor.getScmUsername(),
96                      releaseDescriptor.getScmPassword(),
97                      releaseDescriptor.getScmId(),
98                      releaseEnvironment.getSettings(),
99                      secDispatcher,
100                     getLog() );
101                     
102         releaseDescriptor.setScmUsername( credential.getUsername() );
103         releaseDescriptor.setScmPassword( credential.getPassword() );
104         logInfo( result, "SCM credential selected : " + credential.getUsername() 
105             + ( StringUtils.isEmpty( credential.getUsername() ) ? "" : "/XXXXXXXX" ) );
106         
107         // 2/ check basedir is in scm (svn info, see cxx)
108         //    check all reactor project baseDir ?
109         
110         // choose which basedir to trust !
111         /*
112          * basedir = ReleaseUtil.getRootProject( reactorProjects ).getBasedir().getAbsolutePath();
113          * basedir = releaseDescriptor.getWorkingDirectory();
114          * basedir = ReleaseUtil.getCommonBasedir( reactorProjects );
115          */ 
116         MavenProject rootProject = ReleaseUtil.getRootProject( reactorProjects );
117         File rootBasedir = rootProject.getBasedir();
118         Path rootPath = rootBasedir.toPath();
119         String rootProjectId =
120                 ArtifactUtils.versionlessKey( rootProject.getGroupId(), rootProject.getArtifactId() );
121         String rootScmProvider = ScmUrlUtils.getProvider( releaseDescriptor.getScmSourceUrl() );
122         SvnInfo rootBasedirSvnInfo = new SvnInfo();
123         Path rootSvnDir = null;
124         if ( StringUtils.equalsIgnoreCase( "svn", rootScmProvider ) )
125         {
126             // svn case
127             rootBasedirSvnInfo = SvnService.getSvnInfo( rootBasedir, null,
128                 rootBasedir.getAbsolutePath(), getLog(), true );
129             if ( !rootBasedirSvnInfo.isValide() )
130             {
131                 throw new MojoFailureException( "Main project \"" + rootProjectId + "\" local directory ("
132                     + rootBasedir + ") is not under scm control, while scm (" + rootScmProvider + ") claimed to be." );
133             }
134             else
135             {
136                 try 
137                 {
138                     rootSvnDir = new File( new URL( rootBasedirSvnInfo.getSvnUrl() ).getPath() ).toPath();
139                 }
140                 catch ( MalformedURLException e )
141                 {
142                 }
143                 logInfo( result, "Main project \"" + rootProjectId + "\" local directory (" + rootBasedir 
144                     + ") is under SCM configuration" );
145                     
146                 String pomSCMUrl = ScmUrlUtils.getProviderSpecificPart( releaseDescriptor.getScmSourceUrl() );
147                 if ( !StringUtils.equalsIgnoreCase( trimTrailingFileSepartorChar( pomSCMUrl ),
148                     trimTrailingFileSepartorChar( rootBasedirSvnInfo.getSvnUrl() ) ) )
149                 {
150                     throw new MojoFailureException( "Main project \"" + rootProjectId + "\" local directory ("
151                         + rootBasedir + ") SCM info (" + rootBasedirSvnInfo.getSvnUrl() 
152                         + "), doesnt match project SCM info (" + pomSCMUrl + "). Please fix this prior to continue" );
153                 }
154                 else
155                 {
156                     logInfo( result, "Main project \"" + rootProjectId + "\" local directory ("
157                         + rootBasedir + ") SCM info (" + rootBasedirSvnInfo.getSvnUrl() 
158                         + "), match project SCM info" );
159                 }
160             }
161         }
162         else
163         {
164             logInfo( result, "Main project SCM concistancy check not supported for \"" + rootScmProvider + "\"" );
165             //throw new MojoFailureException( scmProvider + " not yet supported" ); 
166         }
167         
168         List<MavenProject> projectToExclude = new ArrayList<MavenProject>();
169         
170         // check dir tree and scm tree
171         for ( MavenProject subProject : reactorProjects )
172         {
173 
174             String subProjectId =
175                 ArtifactUtils.versionlessKey( subProject.getGroupId(), subProject.getArtifactId() );
176                 
177             /*if (subProjectId.contains( "module" ) )
178             {
179                 logInfo( result, "remove \"" + subProjectId + "\" because !" );
180                 projectToExclude.add( subProject );
181                 continue;
182             }*/
183                 
184             if ( subProjectId.equals( rootProjectId ) ) 
185             {
186                 logInfo( result, "skip exam of \"" + subProjectId + "\" since it is the root project :\""
187                     + rootProjectId + "\"" );
188                 continue;
189             }
190             
191             File basedir = subProject.getBasedir();
192             
193             Path path = basedir.toPath();
194          
195             if ( ! path.startsWith( rootPath ) )
196             {
197                 logInfo( result, "Sub project \"" + subProjectId 
198                 + "\" excluded since its local directory location is not included under root project local directory ("
199                 + rootBasedir + ")" );
200                 projectToExclude.add( subProject );
201                 continue;     
202             }
203             else
204             {
205                 logInfo( result, "Sub project \"" + subProjectId + "\" local directory (" + basedir 
206                     + ") is under root project local directory (" + rootBasedir + ")" );
207             }
208 
209             if ( StringUtils.equalsIgnoreCase( "svn", rootScmProvider ) )
210             {
211                 // svn case
212                 SvnInfo basedirSvnInfo = SvnService.getSvnInfo( basedir, null, basedir.getAbsolutePath(), getLog(), true );
213                 if ( !basedirSvnInfo.isValide() )
214                 {
215                     logInfo( result, "Sub project \"" + subProjectId 
216                         + "\" excluded since its local directory is not under SCM control" );
217                     projectToExclude.add( subProject );
218                     continue;
219                 }
220                 else
221                 {
222                     logInfo( result, "Sub project \"" + subProjectId + "\" local directory (" 
223                         + basedir + ") is under SCM control" );
224 
225                     if ( subProject.getScm() != null )
226                     {
227                         String pomSCMUrl = null;
228                         if ( subProject.getScm().getDeveloperConnection() != null )
229                         {
230                             pomSCMUrl = ScmUrlUtils.getProviderSpecificPart( subProject.getScm().getDeveloperConnection() );
231                         }
232                         else if ( subProject.getScm().getConnection() != null )
233                         {
234                             pomSCMUrl = ScmUrlUtils.getProviderSpecificPart( subProject.getScm().getConnection() );
235                         }
236 
237                         if ( !StringUtils.equalsIgnoreCase( trimTrailingFileSepartorChar( pomSCMUrl ),
238                             trimTrailingFileSepartorChar( basedirSvnInfo.getSvnUrl() ) ) )
239                         {
240                           throw new MojoFailureException( "Sub project \"" + subProjectId + "\" local directory ("
241                               + basedir + ") SCM info (" + basedirSvnInfo.getSvnUrl() 
242                               + "), doesnt match project SCM info (" + pomSCMUrl + "). Please fix this prior to continue" );
243                         }
244                         else
245                         {
246                           logInfo( result, "Sub project \"" + subProjectId + "\" local directory ("
247                               + basedir + ") SCM info (" + basedirSvnInfo.getSvnUrl() 
248                               + "), match project SCM info" );
249                         }
250                         
251                     }
252                         
253                     if ( rootBasedirSvnInfo.isValide() )
254                     {
255                         if ( !StringUtils.equalsIgnoreCase( rootBasedirSvnInfo.getSvnRoot(),
256                             basedirSvnInfo.getSvnRoot() ) )
257                         {
258                             logInfo( result, "Sub project \"" + subProjectId
259                                 + "\" excluded since its svn root (" + basedirSvnInfo.getSvnRoot()
260                                 + ") differs from root project's one (" 
261                                 + rootBasedirSvnInfo.getSvnRoot() + ")" );
262                             projectToExclude.add( subProject );
263                         }
264                         else 
265                         {
266                             logInfo( result, "Sub project \"" + subProjectId + "\" svn root location (" 
267                                 + rootBasedirSvnInfo.getSvnRoot() + ") is the same as root project's one \"" 
268                                 +  rootProjectId + "\"" );
269                             Path svnDir = null;
270                             try
271                             {
272                                 svnDir = new File( new URL( basedirSvnInfo.getSvnUrl() ).getPath() ).toPath();
273                             }
274                             catch ( MalformedURLException e )
275                             {
276                             }
277                             if ( null != rootSvnDir && null != svnDir )
278                             {
279                                 if ( !svnDir.startsWith( rootSvnDir ) )
280                                 {
281                                     logInfo( result, "Sub project \"" + subProjectId 
282                                         + "\" excluded since its svn location (" + svnDir 
283                                         + ") is not included under root project svn location (" +  rootSvnDir + ")"  );
284                                     projectToExclude.add( subProject );
285                                     continue;     
286                                 }
287                                 else
288                                 {
289                                     logInfo( result, "Sub project \"" + subProjectId + "\" svn location ("
290                                         + svnDir + ") is under root project svn location (" +  rootSvnDir + ")" );
291                                 }
292                             }
293                         }
294                     }
295                 }
296             }
297         }
298         
299         for ( MavenProject subProject : projectToExclude )
300         {
301             
302             reactorProjects.remove( subProject );
303         } 
304         
305         return result;
306     }
307     
308     private String trimTrailingFileSepartorChar( String path )
309     {
310         if (null != path)
311         {
312             return path.replaceAll( "[\\/]+$", "" );
313         }
314         return null;
315     }
316 }