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.BuildDefinitionDao;
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.Project;
30 import org.apache.maven.continuum.model.scm.ScmResult;
31 import org.apache.maven.continuum.notification.ContinuumNotificationDispatcher;
32 import org.apache.maven.continuum.project.ContinuumProjectState;
33 import org.apache.maven.continuum.store.ContinuumStoreException;
34 import org.apache.maven.scm.ScmException;
35 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
36 import org.apache.maven.scm.manager.NoSuchScmProviderException;
37 import org.apache.maven.scm.repository.ScmRepositoryException;
38 import org.codehaus.plexus.util.StringUtils;
39
40 import java.io.File;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44
45
46
47
48
49
50 public class CheckoutProjectContinuumAction
51 extends AbstractContinuumAction
52 {
53 private static final String KEY_SCM_USERNAME = "scmUserName";
54
55 private static final String KEY_SCM_PASSWORD = "scmUserPassword";
56
57 private static final String KEY_PROJECT_RELATIVE_PATH = "project-relative-path";
58
59 private static final String KEY_CHECKOUT_SCM_RESULT = "checkout-result";
60
61
62
63
64 private ContinuumNotificationDispatcher notifier;
65
66
67
68
69 private ContinuumScm scm;
70
71
72
73
74 private BuildDefinitionDao buildDefinitionDao;
75
76
77
78
79 private ProjectDao projectDao;
80
81 public void execute( Map context )
82 throws ContinuumStoreException
83 {
84 Project project = projectDao.getProject( getProject( context ).getId() );
85
86 BuildDefinition buildDefinition = getBuildDefinition( context );
87
88 if ( buildDefinition != null )
89 {
90 buildDefinition = buildDefinitionDao.getBuildDefinition( buildDefinition.getId() );
91 }
92
93 int originalState = project.getState();
94
95 project.setState( ContinuumProjectState.CHECKING_OUT );
96
97 projectDao.updateProject( project );
98
99 File workingDirectory = getWorkingDirectory( context );
100
101
102
103
104
105 ScmResult result;
106
107 List<Project> projectsWithCommonScmRoot = getListOfProjectsInGroupWithCommonScmRoot( context );
108
109 try
110 {
111 String scmUserName = getScmUsername( context, project.getScmUsername() );
112 String scmPassword = getScmPassword( context, project.getScmPassword() );
113 String scmRootUrl = getProjectScmRootUrl( context, project.getScmUrl() );
114
115 ContinuumScmConfiguration config = createScmConfiguration( project, workingDirectory, scmUserName,
116 scmPassword, scmRootUrl, isRootDirectory(
117 context ) );
118
119 String tag = config.getTag();
120 getLogger().info(
121 "Checking out project: '" + project.getName() + "', id: '" + project.getId() + "' " + "to '" +
122 workingDirectory + "'" + ( tag != null ? " with branch/tag " + tag + "." : "." ) );
123
124 CheckOutScmResult checkoutResult = scm.checkout( config );
125 if ( StringUtils.isNotEmpty( checkoutResult.getRelativePathProjectDirectory() ) )
126 {
127 setProjectRelativePath( context, checkoutResult.getRelativePathProjectDirectory() );
128 }
129
130 if ( !checkoutResult.isSuccess() )
131 {
132
133
134 String msg = "Error while checking out the code for project: '" + project.getName() + "', id: '" +
135 project.getId() + "' to '" + workingDirectory.getAbsolutePath() + "'" +
136 ( tag != null ? " with branch/tag " + tag + "." : "." );
137 getLogger().warn( msg );
138
139 getLogger().warn( "Command output: " + checkoutResult.getCommandOutput() );
140
141 getLogger().warn( "Provider message: " + checkoutResult.getProviderMessage() );
142 }
143 else
144 {
145 getLogger().info( "Checked out " + checkoutResult.getCheckedOutFiles().size() + " files." );
146 }
147
148 result = convertScmResult( checkoutResult );
149 }
150 catch ( ScmRepositoryException e )
151 {
152 result = new ScmResult();
153
154 result.setSuccess( false );
155
156 result.setProviderMessage( e.getMessage() + ": " + getValidationMessages( e ) );
157
158 getLogger().error( e.getMessage(), e );
159 }
160 catch ( NoSuchScmProviderException e )
161 {
162
163 result = new ScmResult();
164
165 result.setSuccess( false );
166
167 result.setProviderMessage( e.getMessage() );
168
169 getLogger().error( e.getMessage(), e );
170 }
171 catch ( ScmException e )
172 {
173 result = new ScmResult();
174
175 result.setSuccess( false );
176
177 result.setException( ContinuumUtils.throwableMessagesToString( e ) );
178
179 getLogger().error( e.getMessage(), e );
180 }
181 catch ( Throwable t )
182 {
183
184
185 result = new ScmResult();
186
187 result.setSuccess( false );
188
189 result.setException( ContinuumUtils.throwableMessagesToString( t ) );
190
191 getLogger().error( t.getMessage(), t );
192 }
193 finally
194 {
195 String relativePath = getProjectRelativePath( context );
196
197 if ( StringUtils.isNotEmpty( relativePath ) )
198 {
199 project.setRelativePath( relativePath );
200 }
201
202 project = projectDao.getProject( project.getId() );
203
204 if ( originalState == ContinuumProjectState.NEW )
205 {
206 project.setState( ContinuumProjectState.CHECKEDOUT );
207 }
208 else
209 {
210 project.setState( originalState );
211 }
212
213 projectDao.updateProject( project );
214
215
216
217 for ( Project projectWithCommonScmRoot : projectsWithCommonScmRoot )
218 {
219 projectWithCommonScmRoot = projectDao.getProject( projectWithCommonScmRoot.getId() );
220 if ( projectWithCommonScmRoot != null && projectWithCommonScmRoot.getId() != project.getId() &&
221 projectWithCommonScmRoot.getState() == ContinuumProjectState.NEW )
222 {
223 projectWithCommonScmRoot.setState( ContinuumProjectState.CHECKEDOUT );
224 projectDao.updateProject( projectWithCommonScmRoot );
225 }
226 }
227
228 notifier.checkoutComplete( project, buildDefinition );
229 }
230
231 setCheckoutScmResult( context, result );
232 setProject( context, project );
233 }
234
235 private ContinuumScmConfiguration createScmConfiguration( Project project, File workingDirectory,
236 String scmUserName, String scmPassword, String scmRootUrl,
237 boolean isRootDirectory )
238 {
239 ContinuumScmConfiguration config = new ContinuumScmConfiguration();
240
241 if ( project.isCheckedOutInSingleDirectory() && scmRootUrl != null && !"".equals( scmRootUrl ) &&
242 isRootDirectory )
243 {
244 config.setUrl( scmRootUrl );
245 }
246 else
247 {
248 config.setUrl( project.getScmUrl() );
249 }
250
251
252 config = ContinuumScmUtils.setSCMCredentialsforSSH( config, config.getUrl(), scmUserName, scmPassword );
253
254 config.setUseCredentialsCache( project.isScmUseCache() );
255 config.setWorkingDirectory( workingDirectory );
256 config.setTag( project.getScmTag() );
257 return config;
258 }
259
260 private ScmResult convertScmResult( CheckOutScmResult scmResult )
261 {
262 ScmResult result = new ScmResult();
263
264 result.setSuccess( scmResult.isSuccess() );
265
266 result.setCommandLine( maskPassword( scmResult.getCommandLine() ) );
267
268 result.setCommandOutput( scmResult.getCommandOutput() );
269
270 result.setProviderMessage( scmResult.getProviderMessage() );
271
272 return result;
273 }
274
275
276 private String maskPassword( String commandLine )
277 {
278 String cmd = commandLine;
279
280 if ( cmd != null && cmd.startsWith( "svn" ) )
281 {
282 String pwdString = "--password";
283
284 if ( cmd.indexOf( pwdString ) > 0 )
285 {
286 int index = cmd.indexOf( pwdString ) + pwdString.length() + 1;
287
288 int nextSpace = cmd.indexOf( " ", index );
289
290 cmd = cmd.substring( 0, index ) + "********" + cmd.substring( nextSpace );
291 }
292 }
293
294 return cmd;
295 }
296
297 private String getValidationMessages( ScmRepositoryException ex )
298 {
299 List<String> messages = ex.getValidationMessages();
300
301 StringBuffer message = new StringBuffer();
302
303 if ( messages != null && !messages.isEmpty() )
304 {
305 for ( Iterator<String> i = messages.iterator(); i.hasNext(); )
306 {
307 message.append( i.next() );
308
309 if ( i.hasNext() )
310 {
311 message.append( System.getProperty( "line.separator" ) );
312 }
313 }
314 }
315 return message.toString();
316 }
317
318 public static String getScmUsername( Map<String, Object> context, String defaultValue )
319 {
320 return getString( context, KEY_SCM_USERNAME, defaultValue );
321 }
322
323 public static void setScmUsername( Map<String, Object> context, String scmUsername )
324 {
325 context.put( KEY_SCM_USERNAME, scmUsername );
326 }
327
328 public static String getScmPassword( Map<String, Object> context, String defaultValue )
329 {
330 return getString( context, KEY_SCM_PASSWORD, defaultValue );
331 }
332
333 public static void setScmPassword( Map<String, Object> context, String scmPassword )
334 {
335 context.put( KEY_SCM_PASSWORD, scmPassword );
336 }
337
338 public static String getProjectRelativePath( Map<String, Object> context )
339 {
340 return getString( context, KEY_PROJECT_RELATIVE_PATH, "" );
341 }
342
343 public static void setProjectRelativePath( Map<String, Object> context, String projectRelativePath )
344 {
345 context.put( KEY_PROJECT_RELATIVE_PATH, projectRelativePath );
346 }
347
348 public static ScmResult getCheckoutScmResult( Map<String, Object> context, ScmResult defaultValue )
349 {
350 return (ScmResult) getObject( context, KEY_CHECKOUT_SCM_RESULT, defaultValue );
351 }
352
353 public static void setCheckoutScmResult( Map<String, Object> context, ScmResult scmResult )
354 {
355 context.put( KEY_CHECKOUT_SCM_RESULT, scmResult );
356 }
357 }