1 package org.apache.maven.continuum.core.action;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.continuum.dao.BuildResultDao;
23 import org.apache.continuum.dao.ProjectDao;
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.continuum.utils.ContinuumUtils;
28 import org.apache.maven.continuum.model.project.BuildDefinition;
29 import org.apache.maven.continuum.model.project.BuildResult;
30 import org.apache.maven.continuum.model.project.Project;
31 import org.apache.maven.continuum.model.scm.ChangeFile;
32 import org.apache.maven.continuum.model.scm.ChangeSet;
33 import org.apache.maven.continuum.model.scm.ScmResult;
34 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
35 import org.apache.maven.continuum.project.ContinuumProjectState;
36 import org.apache.maven.continuum.store.ContinuumObjectNotFoundException;
37 import org.apache.maven.continuum.store.ContinuumStoreException;
38 import org.apache.maven.continuum.utils.WorkingDirectoryService;
39 import org.apache.maven.scm.ScmException;
40 import org.apache.maven.scm.ScmFile;
41 import org.apache.maven.scm.command.update.UpdateScmResult;
42 import org.apache.maven.scm.manager.NoSuchScmProviderException;
43 import org.apache.maven.scm.repository.ScmRepositoryException;
44
45 import java.io.File;
46 import java.util.Date;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Map;
50
51
52
53
54
55
56 public class UpdateWorkingDirectoryFromScmContinuumAction
57 extends AbstractContinuumAction
58 {
59 private static final String KEY_UPDATE_SCM_RESULT = "update-result";
60
61
62
63
64 private ContinuumNotificationDispatcher notifier;
65
66
67
68
69 private ContinuumScm scm;
70
71
72
73
74 private WorkingDirectoryService workingDirectoryService;
75
76
77
78
79 private BuildResultDao buildResultDao;
80
81
82
83
84 private ProjectDao projectDao;
85
86 public void execute( Map context )
87 throws ScmRepositoryException, NoSuchScmProviderException, ScmException, ContinuumObjectNotFoundException,
88 ContinuumStoreException
89 {
90 Project project = projectDao.getProject( getProject( context ).getId() );
91
92 BuildDefinition buildDefinition = getBuildDefinition( context );
93
94 UpdateScmResult scmResult;
95
96 ScmResult result;
97
98 Date latestUpdateDate = null;
99
100 int originalState = project.getState();
101
102 project.setState( ContinuumProjectState.UPDATING );
103
104 projectDao.updateProject( project );
105
106 try
107 {
108 BuildResult buildResult = buildResultDao.getLatestBuildResultForProject( project.getId() );
109
110 latestUpdateDate = new Date( buildResult.getStartTime() );
111 }
112 catch ( Exception e )
113 {
114 }
115
116 try
117 {
118 notifier.checkoutStarted( project, buildDefinition );
119
120 List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
121 String projectScmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
122
123
124 File workingDirectory = workingDirectoryService.getWorkingDirectory( project, projectScmRootUrl,
125 projectsWithCommonScmRoot );
126
127 ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory, projectScmRootUrl );
128 config.setLatestUpdateDate( latestUpdateDate );
129 String tag = config.getTag();
130 String msg =
131 project.getName() + "', id: '" + project.getId() + "' to '" + workingDirectory.getAbsolutePath() + "'" +
132 ( tag != null ? " with branch/tag " + tag + "." : "." );
133 getLogger().info( "Updating project: " + msg );
134 scmResult = scm.update( config );
135
136 if ( !scmResult.isSuccess() )
137 {
138 getLogger().warn( "Error while updating the code for project: '" + msg );
139
140 getLogger().warn( "Command output: " + scmResult.getCommandOutput() );
141
142 getLogger().warn( "Provider message: " + scmResult.getProviderMessage() );
143 }
144
145 if ( scmResult.getUpdatedFiles() != null && scmResult.getUpdatedFiles().size() > 0 )
146 {
147 getLogger().info( "Updated " + scmResult.getUpdatedFiles().size() + " files." );
148 }
149
150 result = convertScmResult( scmResult );
151 }
152 catch ( ScmRepositoryException e )
153 {
154 result = new ScmResult();
155
156 result.setSuccess( false );
157
158 result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
159
160 getLogger().error( e.getMessage(), e );
161 }
162 catch ( NoSuchScmProviderException e )
163 {
164
165 result = new ScmResult();
166
167 result.setSuccess( false );
168
169 result.setProviderMessage( e.getMessage() );
170
171 getLogger().error( e.getMessage(), e );
172 }
173 catch ( ScmException e )
174 {
175 result = new ScmResult();
176
177 result.setSuccess( false );
178
179 result.setException( ContinuumUtils.throwableMessagesToString( e ) );
180
181 getLogger().error( e.getMessage(), e );
182 }
183 finally
184 {
185
186 try
187 {
188 project = projectDao.getProject( project.getId() );
189
190 project.setState( originalState );
191
192 projectDao.updateProject( project );
193 }
194 catch ( Exception e )
195 {
196
197 getLogger().error( e.getMessage(), e );
198 }
199
200 notifier.checkoutComplete( project, buildDefinition );
201 }
202
203 setUpdateScmResult( context, result );
204 AbstractContinuumAction.setProject( context, project );
205 }
206
207 private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory,
208 String scmRootUrl )
209 {
210 ContinuumScmConfiguration config = new ContinuumScmConfiguration();
211
212 if ( project.isCheckedOutInSingleDirectory() && scmRootUrl != null && !"".equals( scmRootUrl ) )
213 {
214 config.setUrl( scmRootUrl );
215 }
216 else
217 {
218 config.setUrl( project.getScmUrl() );
219 }
220
221
222 config = ContinuumScmUtils.setSCMCredentialsforSSH( config, config.getUrl(), project.getScmUsername(),
223 project.getScmPassword() );
224
225 config.setUseCredentialsCache( project.isScmUseCache() );
226 config.setWorkingDirectory( workingDirectory );
227 config.setTag( project.getScmTag() );
228 return config;
229 }
230
231 private ScmResult convertScmResult( UpdateScmResult scmResult )
232 {
233 ScmResult result = new ScmResult();
234
235 result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
236
237 result.setSuccess( scmResult.isSuccess() );
238
239 result.setCommandOutput( scmResult.getCommandOutput() );
240
241 result.setProviderMessage( scmResult.getProviderMessage() );
242
243 if ( scmResult.getChanges() != null && !scmResult.getChanges().isEmpty() )
244 {
245 for ( org.apache.maven.scm.ChangeSet scmChangeSet : (List<org.apache.maven.scm.ChangeSet>) scmResult.getChanges() )
246 {
247 ChangeSet change = new ChangeSet();
248
249 change.setAuthor( scmChangeSet.getAuthor() );
250
251 change.setComment( scmChangeSet.getComment() );
252
253 if ( scmChangeSet.getDate() != null )
254 {
255 change.setDate( scmChangeSet.getDate().getTime() );
256 }
257
258 if ( scmChangeSet.getFiles() != null )
259 {
260 for ( org.apache.maven.scm.ChangeFile f : (List<org.apache.maven.scm.ChangeFile>) scmChangeSet.getFiles() )
261 {
262 ChangeFile file = new ChangeFile();
263
264 file.setName( f.getName() );
265
266 file.setRevision( f.getRevision() );
267
268 change.addFile( file );
269 }
270 }
271
272 result.addChange( change );
273 }
274 }
275 else
276 {
277
278
279 ChangeSet changeSet = convertScmFileSetToChangeSet( scmResult.getUpdatedFiles() );
280
281 if ( changeSet != null )
282 {
283 result.addChange( changeSet );
284 }
285
286 }
287
288 return result;
289 }
290
291 private static ChangeSet convertScmFileSetToChangeSet( List<ScmFile> files )
292 {
293 ChangeSet changeSet = null;
294
295 if ( files != null && !files.isEmpty() )
296 {
297 changeSet = new ChangeSet();
298
299
300 for ( ScmFile scmFile : files )
301 {
302 ChangeFile file = new ChangeFile();
303
304 file.setName( scmFile.getPath() );
305
306
307
308 file.setStatus( scmFile.getStatus().toString() );
309
310 changeSet.addFile( file );
311 }
312 }
313 return changeSet;
314 }
315
316
317 private String maskPassword( String commandLine )
318 {
319 String cmd = commandLine;
320
321 if ( cmd != null && cmd.startsWith( "svn" ) )
322 {
323 String pwdString = "--password";
324
325 if ( cmd.indexOf( pwdString ) > 0 )
326 {
327 int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
328
329 int nextSpace = cmd.indexOf( " ", index );
330
331 cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
332 }
333 }
334
335 return cmd;
336 }
337
338 private String getValidationMessages( ScmRepositoryException ex )
339 {
340 List<String> messages = ex.getValidationMessages();
341
342 StringBuffer message = new StringBuffer();
343
344 if ( messages != null && !messages.isEmpty() )
345 {
346 for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
347 {
348 message.append( i.next() );
349
350 if ( i.hasNext() )
351 {
352 message.append( System.getProperty( "line.separator" ) );
353 }
354 }
355 }
356 return message.toString();
357 }
358
359 public static ScmResult getUpdateScmResult( Map<String, Object> context, ScmResult defaultValue )
360 {
361 return (ScmResult) getObject( context, KEY_UPDATE_SCM_RESULT, defaultValue );
362 }
363
364 public static void setUpdateScmResult( Map<String, Object> context, ScmResult scmResult )
365 {
366 context.put( KEY_UPDATE_SCM_RESULT, scmResult );
367 }
368 }