View Javadoc

1   package org.apache.continuum.buildagent.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.buildagent.configuration.BuildAgentConfigurationService;
23  import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
24  import org.apache.continuum.scm.ContinuumScm;
25  import org.apache.continuum.scm.ContinuumScmConfiguration;
26  import org.apache.continuum.scm.ContinuumScmUtils;
27  import org.apache.maven.continuum.model.project.Project;
28  import org.apache.maven.continuum.model.scm.ScmResult;
29  import org.apache.maven.scm.ScmException;
30  import org.apache.maven.scm.command.checkout.CheckOutScmResult;
31  import org.apache.maven.scm.manager.NoSuchScmProviderException;
32  import org.apache.maven.scm.repository.ScmRepositoryException;
33  import org.codehaus.plexus.action.AbstractAction;
34  
35  import java.io.File;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.Map;
39  
40  /**
41   * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="checkout-agent-project"
42   */
43  public class CheckoutProjectAction
44      extends AbstractAction
45  {
46      /**
47       * @plexus.requirement
48       */
49      private BuildAgentConfigurationService buildAgentConfigurationService;
50  
51      /**
52       * @plexus.requirement
53       */
54      private ContinuumScm scm;
55  
56      public void execute( Map context )
57          throws Exception
58      {
59          Project project = ContinuumBuildAgentUtil.getProject( context );
60  
61          File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
62  
63          // ----------------------------------------------------------------------
64          // Check out the project
65          // ----------------------------------------------------------------------
66  
67          ScmResult result;
68  
69          try
70          {
71              String scmUserName = ContinuumBuildAgentUtil.getString( context, ContinuumBuildAgentUtil.KEY_SCM_USERNAME,
72                                                                      project.getScmUsername() );
73              String scmPassword = ContinuumBuildAgentUtil.getString( context, ContinuumBuildAgentUtil.KEY_SCM_PASSWORD,
74                                                                      project.getScmPassword() );
75  
76              ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory, scmUserName,
77                                                                         scmPassword );
78  
79              String tag = config.getTag();
80              getLogger().info(
81                  "Checking out project: '" + project.getName() + "', id: '" + project.getId() + "' " + "to '" +
82                      workingDirectory + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." ) );
83  
84              CheckOutScmResult checkoutResult = scm.checkout( config );
85              //if ( StringUtils.isNotEmpty( checkoutResult.getRelativePathProjectDirectory() ) )
86              //{
87              //    context.put( AbstractContinuumAction.KEY_PROJECT_RELATIVE_PATH,
88              //                 checkoutResult.getRelativePathProjectDirectory() );
89              //}
90  
91              if ( !checkoutResult.isSuccess() )
92              {
93                  // TODO: is it more appropriate to return this in the converted result so that it can be presented to
94                  // the user?
95                  String msg = "Error while checking out the code for project: '" + project.getName() + "', id: '" +
96                      project.getId() + "' to '" + workingDirectory.getAbsolutePath() + "'" +
97                      ( tag != null ? " with branch/tag " + tag + "." : "." );
98                  getLogger().warn( msg );
99  
100                 getLogger().warn( "Command output: " + checkoutResult.getCommandOutput() );
101 
102                 getLogger().warn( "Provider message: " + checkoutResult.getProviderMessage() );
103             }
104             else
105             {
106                 getLogger().info( "Checked out " + checkoutResult.getCheckedOutFiles().size() + " files." );
107             }
108 
109             result = convertScmResult( checkoutResult );
110         }
111         catch ( ScmRepositoryException e )
112         {
113             result = new ScmResult();
114 
115             result.setSuccess( false );
116 
117             result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
118 
119             getLogger().error( e.getMessage(), e );
120         }
121         catch ( NoSuchScmProviderException e )
122         {
123             // TODO: this is not making it back into a result of any kind - log it at least. Same is probably the case for ScmException
124             result = new ScmResult();
125 
126             result.setSuccess( false );
127 
128             result.setProviderMessage( e.getMessage() );
129 
130             getLogger().error( e.getMessage(), e );
131         }
132         catch ( ScmException e )
133         {
134             result = new ScmResult();
135 
136             result.setSuccess( false );
137 
138             result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( e ) );
139 
140             getLogger().error( e.getMessage(), e );
141         }
142         catch ( Throwable t )
143         {
144             // TODO: do we want this here, or should it be to the logs?
145             // TODO: what throwables do we really get here that we can cope with?
146             result = new ScmResult();
147 
148             result.setSuccess( false );
149 
150             result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( t ) );
151 
152             getLogger().error( t.getMessage(), t );
153         }
154 
155         context.put( ContinuumBuildAgentUtil.KEY_CHECKOUT_SCM_RESULT, result );
156     }
157 
158     private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory,
159                                                               String scmUserName, String scmPassword )
160     {
161         ContinuumScmConfiguration config = new ContinuumScmConfiguration();
162 
163         // CONTINUUM-2628
164         config = ContinuumScmUtils.setSCMCredentialsforSSH( config, project.getScmUrl(), scmUserName, scmPassword );
165 
166         config.setUrl( project.getScmUrl() );
167         config.setUseCredentialsCache( project.isScmUseCache() );
168         config.setWorkingDirectory( workingDirectory );
169         config.setTag( project.getScmTag() );
170         return config;
171     }
172 
173     private ScmResult convertScmResult( CheckOutScmResult scmResult )
174     {
175         ScmResult result = new ScmResult();
176 
177         result.setSuccess( scmResult.isSuccess() );
178 
179         result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
180 
181         result.setCommandOutput( scmResult.getCommandOutput() );
182 
183         result.setProviderMessage( scmResult.getProviderMessage() );
184 
185         return result;
186     }
187 
188     // TODO: migrate to the SvnCommandLineUtils version (preferably properly encapsulated in the provider)
189     private String maskPassword( String commandLine )
190     {
191         String cmd = commandLine;
192 
193         if ( cmd != null && cmd.startsWith( "svn" ) )
194         {
195             String pwdString = "--password";
196 
197             if ( cmd.indexOf( pwdString ) > 0 )
198             {
199                 int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
200 
201                 int nextSpace = cmd.indexOf( " ", index );
202 
203                 cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
204             }
205         }
206 
207         return cmd;
208     }
209 
210     private String getValidationMessages( ScmRepositoryException ex )
211     {
212         List<String> messages = ex.getValidationMessages();
213 
214         StringBuffer message = new StringBuffer();
215 
216         if ( messages != null && !messages.isEmpty() )
217         {
218             for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
219             {
220                 message.append( i.next() );
221 
222                 if ( i.hasNext() )
223                 {
224                     message.append( System.getProperty( "line.separator" ) );
225                 }
226             }
227         }
228         return message.toString();
229     }
230 }