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.Date;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  
28  import org.apache.continuum.buildagent.configuration.BuildAgentConfigurationService;
29  import org.apache.continuum.buildagent.utils.ContinuumBuildAgentUtil;
30  import org.apache.continuum.scm.ContinuumScm;
31  import org.apache.continuum.scm.ContinuumScmConfiguration;
32  import org.apache.maven.continuum.model.project.Project;
33  import org.apache.maven.continuum.model.scm.ChangeFile;
34  import org.apache.maven.continuum.model.scm.ChangeSet;
35  import org.apache.maven.continuum.model.scm.ScmResult;
36  import org.apache.maven.scm.ScmException;
37  import org.apache.maven.scm.ScmFile;
38  import org.apache.maven.scm.command.update.UpdateScmResult;
39  import org.apache.maven.scm.manager.NoSuchScmProviderException;
40  import org.apache.maven.scm.repository.ScmRepositoryException;
41  import org.codehaus.plexus.action.AbstractAction;
42  
43  /**
44   * @plexus.component role="org.codehaus.plexus.action.Action" role-hint="update-agent-working-directory"
45   */
46  public class UpdateWorkingDirectoryAction
47      extends AbstractAction
48  {
49      /**
50       * @plexus.requirement
51       */
52      private BuildAgentConfigurationService buildAgentConfigurationService;
53  
54      /**
55       * @plexus.requirement
56       */
57      private ContinuumScm scm;
58  
59      public void execute( Map context )
60          throws Exception
61      {
62          Project project = ContinuumBuildAgentUtil.getProject( context );
63  
64          UpdateScmResult scmResult;
65  
66          ScmResult result;
67          
68          try
69          {
70              File workingDirectory = buildAgentConfigurationService.getWorkingDirectory( project.getId() );
71              ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory );
72              config.setLatestUpdateDate( ContinuumBuildAgentUtil.getLatestUpdateDate( context ) );
73              String tag = config.getTag();
74              String msg = project.getName() + "', id: '" + project.getId() + "' to '" +
75                  workingDirectory.getAbsolutePath() + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." );
76              getLogger().info( "Updating project: " + msg );
77              scmResult = scm.update( config );
78  
79              if ( !scmResult.isSuccess() )
80              {
81                  getLogger().warn( "Error while updating the code for project: '" + msg );
82  
83                  getLogger().warn( "Command output: " + scmResult.getCommandOutput() );
84  
85                  getLogger().warn( "Provider message: " + scmResult.getProviderMessage() );
86              }
87  
88              if ( scmResult.getUpdatedFiles() != null && scmResult.getUpdatedFiles().size() > 0 )
89              {
90                  getLogger().info( "Updated " + scmResult.getUpdatedFiles().size() + " files." );
91              }
92  
93              result = convertScmResult( scmResult );
94          }
95          catch ( ScmRepositoryException e )
96          {
97              result = new ScmResult();
98  
99              result.setSuccess( false );
100 
101             result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
102             
103             getLogger().error( e.getMessage(), e);
104         }
105         catch ( NoSuchScmProviderException e )
106         {
107             // TODO: this is not making it back into a result of any kind - log it at least. Same is probably the case for ScmException
108             result = new ScmResult();
109 
110             result.setSuccess( false );
111 
112             result.setProviderMessage( e.getMessage() );
113             
114             getLogger().error( e.getMessage(), e);
115         }
116         catch ( ScmException e )
117         {
118             result = new ScmResult();
119 
120             result.setSuccess( false );
121 
122             result.setException( ContinuumBuildAgentUtil.throwableMessagesToString( e ) );
123             
124             getLogger().error( e.getMessage(), e);
125         }
126 
127         context.put( ContinuumBuildAgentUtil.KEY_UPDATE_SCM_RESULT, result );
128         context.put( ContinuumBuildAgentUtil.KEY_LATEST_UPDATE_DATE, getLatestUpdateDate( result ) );
129     }
130 
131     private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory )
132     {
133         ContinuumScmConfiguration config = new ContinuumScmConfiguration();
134         config.setUrl( project.getScmUrl() );
135         config.setUsername( project.getScmUsername() );
136         config.setPassword( project.getScmPassword() );
137         config.setUseCredentialsCache( project.isScmUseCache() );
138         config.setWorkingDirectory( workingDirectory );
139         config.setTag( project.getScmTag() );
140         return config;
141     }
142 
143     private ScmResult convertScmResult( UpdateScmResult scmResult )
144     {
145         ScmResult result = new ScmResult();
146 
147         result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
148 
149         result.setSuccess( scmResult.isSuccess() );
150 
151         result.setCommandOutput( scmResult.getCommandOutput() );
152 
153         result.setProviderMessage( scmResult.getProviderMessage() );
154 
155         if ( scmResult.getChanges() != null && !scmResult.getChanges().isEmpty() )
156         {
157             for ( org.apache.maven.scm.ChangeSet scmChangeSet : (List<org.apache.maven.scm.ChangeSet>) scmResult.getChanges() )
158             {
159                 ChangeSet change = new ChangeSet();
160 
161                 change.setAuthor( scmChangeSet.getAuthor() );
162 
163                 change.setComment( scmChangeSet.getComment() );
164 
165                 if ( scmChangeSet.getDate() != null )
166                 {
167                     change.setDate( scmChangeSet.getDate().getTime() );
168                 }
169 
170                 if ( scmChangeSet.getFiles() != null )
171                 {
172                     for ( org.apache.maven.scm.ChangeFile f : (List<org.apache.maven.scm.ChangeFile>) scmChangeSet.getFiles() )
173                     {
174                         ChangeFile file = new ChangeFile();
175 
176                         file.setName( f.getName() );
177 
178                         file.setRevision( f.getRevision() );
179 
180                         change.addFile( file );
181                     }
182                 }
183 
184                 result.addChange( change );
185             }
186         }
187         else
188         {
189             // We don't have a changes information probably because provider doesn't have a changelog command
190             // so we use the updated list that contains only the updated files list
191             ChangeSet changeSet = convertScmFileSetToChangeSet( scmResult.getUpdatedFiles() );
192 
193             if ( changeSet != null )
194             {
195                 result.addChange( changeSet );
196             }
197         }
198         return result;
199     }
200 
201     private static ChangeSet convertScmFileSetToChangeSet( List<ScmFile> files )
202     {
203         ChangeSet changeSet = null;
204 
205         if ( files != null && !files.isEmpty() )
206         {
207             changeSet = new ChangeSet();
208 
209             // TODO: author, etc.
210             for ( ScmFile scmFile : files )
211             {
212                 ChangeFile file = new ChangeFile();
213 
214                 file.setName( scmFile.getPath() );
215 
216                 // TODO: revision?
217 
218                 file.setStatus( scmFile.getStatus().toString() );
219 
220                 changeSet.addFile( file );
221             }
222         }
223         return changeSet;
224     }
225 
226     // TODO: migrate to the SvnCommandLineUtils version (preferably properly encapsulated in the provider)
227     private String maskPassword( String commandLine )
228     {
229         String cmd = commandLine;
230 
231         if ( cmd != null && cmd.startsWith( "svn" ) )
232         {
233             String pwdString = "--password";
234 
235             if ( cmd.indexOf( pwdString ) > 0 )
236             {
237                 int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
238 
239                 int nextSpace = cmd.indexOf( " ", index );
240 
241                 cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
242             }
243         }
244 
245         return cmd;
246     }
247     
248     private String getValidationMessages( ScmRepositoryException ex )
249     {
250         List<String> messages = ex.getValidationMessages();
251 
252         StringBuffer message = new StringBuffer();
253 
254         if ( messages != null && !messages.isEmpty() )
255         {
256             for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
257             {
258                 message.append( i.next() );
259 
260                 if ( i.hasNext() )
261                 {
262                     message.append( System.getProperty( "line.separator" ) );
263                 }
264             }
265         }
266         return message.toString();
267     }
268 
269     private Date getLatestUpdateDate( ScmResult result )
270     {
271         List<ChangeSet> changes = result.getChanges();
272 
273         if ( changes != null && !changes.isEmpty() )
274         {
275             long date = 0;
276 
277             for ( ChangeSet change : changes )
278             {
279                 if ( date < change.getDate() )
280                 {
281                     date = change.getDate();
282                 }
283             }
284 
285             if ( date != 0 )
286             {
287                 return new Date( date );
288             }
289         }
290 
291         return null;
292     }
293 }