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