View Javadoc

1   package org.apache.continuum.buildagent.utils;
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.io.PrintWriter;
24  import java.io.StringWriter;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Date;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  
32  import org.apache.continuum.buildagent.buildcontext.BuildContext;
33  import org.apache.maven.continuum.ContinuumException;
34  import org.apache.maven.continuum.model.project.BuildDefinition;
35  import org.apache.maven.continuum.model.project.BuildResult;
36  import org.apache.maven.continuum.model.project.Project;
37  import org.apache.maven.continuum.model.scm.ChangeFile;
38  import org.apache.maven.continuum.model.scm.ChangeSet;
39  import org.apache.maven.continuum.model.scm.ScmResult;
40  import org.codehaus.plexus.util.StringUtils;
41  
42  public class ContinuumBuildAgentUtil
43  {
44      public static final String EOL = System.getProperty( "line.separator" );
45  
46      public static final String KEY_PROJECT_ID = "project-id";
47  
48      public static final String KEY_PROJECT_VERSION = "project-version";
49  
50      public static final String KEY_BUILD_NUMBER = "build-number";
51  
52      public static final String KEY_BUILD_DEFINITION_ID = "builddefinition-id";
53  
54      public static final String KEY_BUILD_DEFINITION_LABEL = "builddefinition-label";
55  
56      public static final String KEY_TRIGGER = "trigger";
57  
58      public static final String KEY_EXECUTOR_ID = "executor-id";
59  
60      public static final String KEY_SCM_URL = "scm-url";
61  
62      public static final String KEY_SCM_USERNAME = "scm-username";
63  
64      public static final String KEY_SCM_PASSWORD = "scm-password";
65  
66      public static final String KEY_BUILD_FILE = "build-file";
67  
68      public static final String KEY_GOALS = "goals";
69  
70      public static final String KEY_ARGUMENTS = "arguments";
71  
72      public static final String KEY_BUILD_FRESH = "build-fresh";
73  
74      public static final String KEY_START_TIME = "start-time";
75  
76      public static final String KEY_END_TIME = "end-time";
77  
78      public static final String KEY_BUILD_ERROR = "build-error";
79  
80      public static final String KEY_BUILD_EXIT_CODE = "build-exit-code";
81  
82      public static final String KEY_BUILD_STATE = "build-state";
83  
84      public static final String KEY_SCM_STATE = "scm-state";
85  
86      public static final String KEY_SCM_COMMAND_OUTPUT = "scm-command-output";
87  
88      public static final String KEY_SCM_COMMAND_LINE = "scm-command-line";
89  
90      public static final String KEY_SCM_PROVIDER_MESSAGE = "scm-provider-message";
91  
92      public static final String KEY_SCM_EXCEPTION = "scm-exception";
93  
94      public static final String KEY_PROJECT_GROUP_ID = "project-group-id";
95  
96      public static final String KEY_PROJECT_GROUP_NAME = "project-group-name";
97  
98      public static final String KEY_SCM_ROOT_ADDRESS = "scm-root-address";
99  
100     public static final String KEY_SCM_ROOT_ID = "scm-root-id";
101 
102     public static final String KEY_SCM_ROOT_STATE = "scm-root-state";
103 
104     public static final String KEY_CHECKOUT_SCM_RESULT = "checkout-scm-result";
105 
106     public static final String KEY_UPDATE_SCM_RESULT = "update-scm-result";
107 
108     public static final String KEY_WORKING_DIRECTORY_EXISTS = "working-directory-exists";
109 
110     public static final String KEY_PROJECT = "project";
111 
112     public static final String KEY_BUILD_DEFINITION = "build-definition";
113 
114     public static final String KEY_SCM_RESULT = "scm-result";
115 
116     public static final String KEY_WORKING_DIRECTORY = "working-directory";
117 
118     public static final String KEY_SCM_SUCCESS = "scm-success";
119 
120     public static final String KEY_SCM_ERROR = "scm-error";
121 
122     public static final String KEY_BUILD_RESULT = "build-result";
123 
124     public static final String KEY_PROJECT_NAME = "project-name";
125 
126     public static final String KEY_BUILD_OUTPUT = "build-output";
127 
128     public static final String KEY_PROJECT_STATE = "project-state";
129 
130     public static final String KEY_INSTALLATION_NAME = "installation-name";
131 
132     public static final String KEY_INSTALLATION_TYPE = "installation-type";
133 
134     public static final String KEY_INSTALLATION_VAR_NAME = "installation-var-name";
135 
136     public static final String KEY_INSTALLATION_VAR_VALUE = "installation-var-value";
137 
138     public static final String KEY_ENVIRONMENTS = "environments";
139 
140     public static final String KEY_LOCAL_REPOSITORY = "local-repository";
141 
142     public static final String KEY_SCM_CHANGES = "scm-changes";
143 
144     public static final String KEY_CHANGESET_AUTHOR = "changeset-author";
145 
146     public static final String KEY_CHANGESET_COMMENT = "changeset-comment";
147 
148     public static final String KEY_CHANGESET_DATE = "changeset-date";
149 
150     public static final String KEY_CHANGESET_FILES = "changeset-files";
151 
152     public static final String KEY_CHANGEFILE_NAME = "changefile-name";
153 
154     public static final String KEY_CHANGEFILE_REVISION = "changefile-revision";
155 
156     public static final String KEY_CHANGEFILE_STATUS = "changefile-status";
157 
158     public static final String KEY_OLD_SCM_RESULT = "old-scm-result";
159 
160     public static final String KEY_OLD_SCM_CHANGES = "old-scm-changes";
161 
162     public static final String KEY_PROJECT_DESCRIPTION = "project-description";
163 
164     public static final String KEY_GROUP_ID = "group-id";
165 
166     public static final String KEY_ARTIFACT_ID = "artifact-id";
167 
168     public static final String KEY_PROJECT_DEVELOPERS = "project-developers";
169 
170     public static final String KEY_PROJECT_DEPENDENCIES = "project-dependencies";
171 
172     public static final String KEY_PROJECT_NOTIFIERS = "project-notifiers";
173 
174     public static final String KEY_PROJECT_URL = "project-url";
175 
176     public static final String KEY_SCM_TAG = "scm-tag";
177 
178     public static final String KEY_PROJECT_PARENT = "project-parent";
179 
180     public static final String KEY_NOTIFIER_TYPE = "notifier-type";
181 
182     public static final String KEY_NOTIFIER_CONFIGURATION = "notifier-configuration";
183 
184     public static final String KEY_NOTIFIER_FROM = "notifier-from";
185 
186     public static final String KEY_NOTIFIER_RECIPIENT_TYPE = "notifier-recipient-type";
187 
188     public static final String KEY_NOTIFIER_ENABLED = "notifier-enabled";
189 
190     public static final String KEY_NOTIFIER_SEND_ON_SUCCESS = "notifier-send-on-success";
191 
192     public static final String KEY_NOTIFIER_SEND_ON_FAILURE = "notifier-send-on-failure";
193 
194     public static final String KEY_NOTIFIER_SEND_ON_ERROR = "notifier-send-on-error";
195 
196     public static final String KEY_NOTIFIER_SEND_ON_SCMFAILURE = "notifier-send-on-scmfailure";
197 
198     public static final String KEY_NOTIFIER_SEND_ON_WARNING = "notifier-send-on-warning";
199 
200     public static final String KEY_PROJECT_DEVELOPER_NAME = "developer-name";
201 
202     public static final String KEY_PROJECT_DEVELOPER_EMAIL = "developer-email";
203 
204     public static final String KEY_PROJECT_DEVELOPER_SCMID = "developer-scmid";
205 
206     public static final String KEY_PROJECT_MODULES = "project-modules";
207 
208     public static final String KEY_MAVEN_PROJECT = "maven-project";
209 
210     public static final String KEY_LATEST_UPDATE_DATE = "latest-update-date";
211 
212     public static final String KEY_BUILD_AGENT_URL = "build-agent-url";
213 
214     public static final String KEY_SCM_TAGBASE = "scm-tagbase";
215 
216     public static final String KEY_PREPARE_GOALS = "preparation-goals";
217 
218     public static final String KEY_SCM_COMMENT_PREFIX = "scm-comment-prefix";
219 
220     public static final String KEY_AUTO_VERSION_SUBMODULES = "auto-version-submodules";
221 
222     public static final String KEY_ADD_SCHEMA = "add-schema";
223 
224     public static final String KEY_USE_RELEASE_PROFILE = "use-release-profile";
225 
226     public static final String KEY_RELEASE_VERSION = "release-version";
227 
228     public static final String KEY_DEVELOPMENT_VERSION = "development-version";
229 
230     public static final String KEY_USE_EDIT_MODE = "use-edit-mode";
231 
232     public static final String KEY_RELEASE_RESULT_CODE = "release-result-code";
233 
234     public static final String KEY_RELEASE_OUTPUT = "release-output";
235 
236     public static final String KEY_BUILD_CONTEXTS = "build-contexts";
237 
238     public static final String KEY_MAX_JOB_EXEC_TIME = "max-job-exec-time";
239 
240     public static final String KEY_RELEASE_STATE = "state";
241 
242     public static final String KEY_RELEASE_PHASES = "release-phases";
243 
244     public static final String KEY_RELEASE_IN_PROGRESS = "release-in-progress";
245 
246     public static final String KEY_COMPLETED_RELEASE_PHASES = "completed-release-phases";
247 
248     public static final String KEY_RELEASE_ERROR = "release-error";
249 
250     public static final String KEY_LOCAL_REPOSITORY_NAME = "repo-name";
251 
252     public static final String KEY_LOCAL_REPOSITORY_LAYOUT = "repo-layout";
253 
254     public static Integer getProjectId( Map<String, Object> context )
255     {
256         return getInteger( context, KEY_PROJECT_ID );
257     }
258 
259     public static String getProjectName( Map<String, Object> context )
260     {
261         return getString( context, KEY_PROJECT_NAME );
262     }
263 
264     public static Integer getProjectState( Map<String, Object> context )
265     {
266         return getInteger( context, KEY_PROJECT_STATE );
267     }
268 
269     public static Integer getBuildDefinitionId( Map<String, Object> context )
270     {
271         return getInteger( context, KEY_BUILD_DEFINITION_ID );
272     }
273 
274     public static String getBuildFile( Map<String, Object> context )
275     {
276         return getString( context, KEY_BUILD_FILE );
277     }
278 
279     public static String getExecutorId( Map<String, Object> context )
280     {
281         return getString( context, KEY_EXECUTOR_ID );
282     }
283 
284     public static String getGoals( Map<String, Object> context )
285     {
286         return getString( context, KEY_GOALS );
287     }
288 
289     public static String getArguments( Map<String, Object> context )
290     {
291         return getString( context, KEY_ARGUMENTS );
292     }
293 
294     public static String getScmUrl( Map<String, Object> context )
295     {
296         return getString( context, KEY_SCM_URL );
297     }
298 
299     public static String getScmUsername( Map<String, Object> context )
300     {
301         return getString( context, KEY_SCM_USERNAME, "" );
302     }
303 
304     public static String getScmPassword( Map<String, Object> context )
305     {
306         return getString( context, KEY_SCM_PASSWORD, "" );
307     }
308 
309     public static boolean isBuildFresh( Map<String, Object> context )
310     {
311         return getBoolean( context, KEY_BUILD_FRESH );
312     }
313 
314     public static int getProjectGroupId( Map<String, Object> context )
315     {
316         return getInteger( context, KEY_PROJECT_GROUP_ID );
317     }
318 
319     public static String getScmRootAddress( Map<String, Object> context )
320     {
321         return getString( context, KEY_SCM_ROOT_ADDRESS );
322     }
323 
324     public static int getScmRootState( Map<String, Object> context )
325     {
326         return getInteger( context, KEY_SCM_ROOT_STATE );
327     }
328 
329     public static Project getProject( Map<String, Object> context )
330     {
331         return (Project) getObject( context, KEY_PROJECT );
332     }
333 
334     public static BuildDefinition getBuildDefinition( Map<String, Object> context )
335     {
336         return (BuildDefinition) getObject( context, KEY_BUILD_DEFINITION );
337     }
338 
339     public static ScmResult getCheckoutScmResult( Map<String, Object> context, Object defaultValue )
340     {
341         return (ScmResult) getObject( context, KEY_CHECKOUT_SCM_RESULT, defaultValue );
342     }
343 
344     public static ScmResult getUpdateScmResult( Map<String, Object> context, Object defaultValue )
345     {
346         return (ScmResult) getObject( context, KEY_UPDATE_SCM_RESULT, defaultValue );
347     }
348 
349     public static ScmResult getScmResult( Map<String, Object> context, Object defaultValue )
350     {
351         return (ScmResult) getObject( context, KEY_SCM_RESULT, defaultValue );
352     }
353 
354     public static int getTrigger( Map<String, Object> context )
355     {
356         return getInteger( context, KEY_TRIGGER );
357     }
358 
359     public static BuildResult getBuildResult( Map<String, Object> context, Object defaultValue )
360     {
361         return (BuildResult) getObject( context, KEY_BUILD_RESULT, defaultValue );
362     }
363 
364     public static Map<String, String> getEnvironments( Map<String, Object> context )
365     {
366         return (Map<String, String>) getObject( context, KEY_ENVIRONMENTS );
367     }
368 
369     public static String getLocalRepository( Map<String, Object> context )
370     {
371         return getString( context, KEY_LOCAL_REPOSITORY, "" );
372     }
373 
374     public static String getProjectVersion( Map<String, Object> context )
375     {
376         return getString( context, KEY_PROJECT_VERSION );
377     }
378 
379     public static String getProjectGroupName( Map<String, Object> context )
380     {
381         return getString( context, KEY_PROJECT_GROUP_NAME );
382     }
383 
384     public static int getBuildNumber( Map<String, Object> context )
385     {
386         return getInteger( context, KEY_BUILD_NUMBER );
387     }
388 
389     public static List<Map<String, Object>> getOldScmChanges( Map<String, Object> context )
390     {
391         return getList( context, KEY_OLD_SCM_CHANGES );
392     }
393 
394     public static String getChangeSetAuthor( Map<String, Object> context )
395     {
396         return getString( context, KEY_CHANGESET_AUTHOR );
397     }
398 
399     public static String getChangeSetComment( Map<String, Object> context )
400     {
401         return getString( context, KEY_CHANGESET_COMMENT );
402     }
403 
404     public static long getChangeSetDate( Map<String, Object> context )
405     {
406         Date date = getDate( context, KEY_CHANGESET_DATE );
407 
408         if ( date == null )
409         {
410             return 0;
411         }
412         else
413         {
414             return date.getTime();
415         }
416     }
417 
418     public static List getChangeSetFiles( Map<String, Object> context )
419     {
420         return getList( context, KEY_CHANGESET_FILES );
421     }
422 
423     public static String getChangeFileName( Map<String, Object> context )
424     {
425         return getString( context, KEY_CHANGEFILE_NAME );
426     }
427 
428     public static String getChangeFileRevision( Map<String, Object> context )
429     {
430         return getString( context, KEY_CHANGEFILE_REVISION );
431     }
432 
433     public static String getChangeFileStatus( Map<String, Object> context )
434     {
435         return getString( context, KEY_CHANGEFILE_STATUS );
436     }
437 
438     public static ScmResult getOldScmResult( Map<String, Object> context, ScmResult defaultValue )
439     {
440         return (ScmResult) getObject( context, KEY_OLD_SCM_RESULT, defaultValue );
441     }
442 
443     public static List getScmChanges( Map<String, Object> context )
444     {
445         return getList( context, KEY_SCM_CHANGES );
446     }
447 
448     public static Date getLatestUpdateDate( Map<String, Object> context )
449     {
450         return getDate( context, KEY_LATEST_UPDATE_DATE );
451     }
452 
453     public static String getBuildAgentUrl( Map<String, Object> context )
454     {
455         return getString( context, KEY_BUILD_AGENT_URL );
456     }
457 
458     public static String getGroupId( Map<String, Object> context )
459     {
460         return getString( context, KEY_GROUP_ID );
461     }
462 
463     public static String getArtifactId( Map<String, Object> context )
464     {
465         return getString( context, KEY_ARTIFACT_ID );
466     }
467 
468     public static Map getReleaseVersion( Map<String, Object> context )
469     {
470         return getMap( context, KEY_RELEASE_VERSION );
471     }
472 
473     public static Map getDevelopmentVersion( Map<String, Object> context )
474     {
475         return getMap( context, KEY_DEVELOPMENT_VERSION );
476     }
477 
478     public static String getScmTagBase( Map<String, Object> context )
479     {
480         return getString( context, KEY_SCM_TAGBASE, "" );
481     }
482 
483     public static String getScmCommentPrefix( Map<String, Object> context )
484     {
485         return getString( context, KEY_SCM_COMMENT_PREFIX, "" );
486     }
487 
488     public static String getScmTag( Map<String, Object> context )
489     {
490         return getString( context, KEY_SCM_TAG, "" );
491     }
492 
493     public static String getPrepareGoals( Map<String, Object> context )
494     {
495         return getString( context, KEY_PREPARE_GOALS, "" );
496     }
497 
498     public static String getUseEditMode( Map<String, Object> context )
499     {
500         return getString( context, KEY_USE_EDIT_MODE, "" );
501     }
502 
503     public static String getAddSchema( Map<String, Object> context )
504     {
505         return getString( context, KEY_ADD_SCHEMA, "" );
506     }
507 
508     public static String getAutoVersionSubmodules( Map<String, Object> context )
509     {
510         return getString( context, KEY_AUTO_VERSION_SUBMODULES, "" );
511     }
512 
513     public static List getBuildContexts( Map<String, Object> context )
514     {
515         return getList( context, KEY_BUILD_CONTEXTS );
516     }
517 
518     public static int getMaxExecutionTime( Map<String, Object> context )
519     {
520         return getInteger( context, KEY_MAX_JOB_EXEC_TIME );
521     }
522 
523     public static String getLocalRepositoryName( Map<String, Object> context )
524     {
525         return getString( context, KEY_LOCAL_REPOSITORY_NAME, "" );
526     }
527 
528     public static String getLocalRepositoryLayout( Map<String, Object> context )
529     {
530         return getString( context, KEY_LOCAL_REPOSITORY_LAYOUT, "" );
531     }
532 
533     public static int getScmRootId( Map<String, Object> context )
534     {
535         return getInteger( context, KEY_SCM_ROOT_ID );
536     }
537 
538     public static String getBuildDefinitionLabel( Map<String, Object> context )
539     {
540         return getString( context, KEY_BUILD_DEFINITION_LABEL, "" );
541     }
542 
543     // ----------------------------------------------------------------------
544     //
545     // ----------------------------------------------------------------------
546 
547     public static String getString( Map<String, Object> context, String key )
548     {
549         return (String) getObject( context, key );
550     }
551 
552     public static String getString( Map<String, Object> context, String key, String defaultValue )
553     {
554         return (String) getObject( context, key, defaultValue );
555     }
556 
557     public static boolean getBoolean( Map<String, Object> context, String key )
558     {
559         return (Boolean) getObject( context, key );
560     }
561 
562     public static boolean getBoolean( Map<String, Object> context, String key, boolean defaultValue )
563     {
564         return (Boolean) getObject( context, key, defaultValue );
565     }
566 
567     public static int getInteger( Map<String, Object> context, String key )
568     {
569         Object obj = getObject( context, key, null );
570 
571         if ( obj == null )
572         {
573             return 0;
574         }
575         else
576         {
577             return (Integer) obj;
578         }
579     }
580 
581     public static List getList( Map<String, Object> context, String key )
582     {
583         Object obj = getObject( context, key, null );
584 
585         if ( obj == null )
586         {
587             return null;
588         }
589         else
590         {
591             List<Object> list = new ArrayList<Object>();
592 
593             if ( obj instanceof Object[] )
594             {
595                 Object[] objA = (Object[]) obj;
596 
597                 list.addAll( Arrays.asList( objA ) );
598             }
599             else
600             {
601                 list = (List<Object>) obj;
602             }
603 
604             return list;
605         }
606     }
607 
608     public static Date getDate( Map<String, Object> context, String key )
609     {
610         Object obj = getObject( context, key, null );
611 
612         if ( obj == null )
613         {
614             return null;
615         }
616         else
617         {
618             return (Date) obj;
619         }
620     }
621 
622     protected static Map getMap( Map<String, Object> context, String key )
623     {
624         Object obj = getObject( context, key, null );
625 
626         if ( obj == null )
627         {
628             return null;
629         }
630         else
631         {
632             return (Map) obj;
633         }
634     }
635 
636     protected static Object getObject( Map<String, Object> context, String key )
637     {
638         if ( !context.containsKey( key ) )
639         {
640             throw new RuntimeException( "Missing key '" + key + "'." );
641         }
642 
643         Object value = context.get( key );
644 
645         if ( value == null )
646         {
647             throw new RuntimeException( "Missing value for key '" + key + "'." );
648         }
649 
650         return value;
651     }
652 
653     protected static Object getObject( Map<String, Object> context, String key, Object defaultValue )
654     {
655         Object value = context.get( key );
656 
657         if ( value == null )
658         {
659             return defaultValue;
660         }
661 
662         return value;
663     }
664 
665     public static String throwableToString( Throwable error )
666     {
667         if ( error == null )
668         {
669             return "";
670         }
671 
672         StringWriter writer = new StringWriter();
673 
674         PrintWriter printer = new PrintWriter( writer );
675 
676         error.printStackTrace( printer );
677 
678         printer.flush();
679 
680         return writer.getBuffer().toString();
681     }
682 
683     public static String throwableMessagesToString( Throwable error )
684     {
685         if ( error == null )
686         {
687             return "";
688         }
689 
690         StringBuffer buffer = new StringBuffer();
691 
692         buffer.append( error.getMessage() );
693 
694         error = error.getCause();
695 
696         while ( error != null )
697         {
698             buffer.append( EOL );
699 
700             buffer.append( error.getMessage() );
701 
702             error = error.getCause();
703         }
704 
705         return buffer.toString();
706     }
707 
708     public static Map<String, Object> createScmResult( BuildContext buildContext )
709     {
710         Map<String, Object> result = new HashMap<String, Object>();
711         ScmResult scmResult = buildContext.getScmResult();
712 
713         result.put( ContinuumBuildAgentUtil.KEY_PROJECT_ID, buildContext.getProjectId() );
714         if ( StringUtils.isEmpty( scmResult.getCommandLine() ) )
715         {
716             result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_LINE, "" );
717         }
718         else
719         {
720             result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_LINE, scmResult.getCommandLine() );
721         }
722         if ( StringUtils.isEmpty( scmResult.getCommandOutput() ) )
723         {
724             result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_OUTPUT, "" );
725         }
726         else
727         {
728             result.put( ContinuumBuildAgentUtil.KEY_SCM_COMMAND_OUTPUT, scmResult.getCommandOutput() );
729         }
730         if ( StringUtils.isEmpty( scmResult.getProviderMessage() ) )
731         {
732             result.put( ContinuumBuildAgentUtil.KEY_SCM_PROVIDER_MESSAGE, "" );
733         }
734         else
735         {
736             result.put( ContinuumBuildAgentUtil.KEY_SCM_PROVIDER_MESSAGE, scmResult.getProviderMessage() );
737         }
738         if ( StringUtils.isEmpty( scmResult.getException() ) )
739         {
740             result.put( ContinuumBuildAgentUtil.KEY_SCM_EXCEPTION, "" );
741         }
742         else
743         {
744             result.put( ContinuumBuildAgentUtil.KEY_SCM_EXCEPTION, scmResult.getException() );
745         }
746         result.put( ContinuumBuildAgentUtil.KEY_SCM_SUCCESS, scmResult.isSuccess() );
747         result.put( ContinuumBuildAgentUtil.KEY_SCM_CHANGES, getScmChanges( scmResult ) );
748 
749         return result;
750     }
751 
752     private static List<Map<String, Object>> getScmChanges( ScmResult scmResult )
753     {
754         List<Map<String, Object>> scmChanges = new ArrayList<Map<String, Object>>();
755 
756         List<ChangeSet> changes = scmResult.getChanges();
757 
758         if ( changes != null )
759         {
760             for ( ChangeSet cs : changes )
761             {
762                 Map<String, Object> changeSet = new HashMap<String, Object>();
763 
764                 if ( StringUtils.isNotEmpty( cs.getAuthor() ) )
765                 {
766                     changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_AUTHOR, cs.getAuthor() );
767                 }
768                 else
769                 {
770                     changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_AUTHOR, "" );
771                 }
772                 if ( StringUtils.isNotEmpty( cs.getComment() ) )
773                 {
774                     changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_COMMENT, cs.getComment() );
775                 }
776                 else
777                 {
778                     changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_COMMENT, "" );
779                 }
780                 if ( cs.getDateAsDate() != null )
781                 {
782                     changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_DATE, cs.getDateAsDate() );
783                 }
784                 changeSet.put( ContinuumBuildAgentUtil.KEY_CHANGESET_FILES, getChangeFiles( cs.getFiles() ) );
785 
786                 scmChanges.add( changeSet );
787             }
788         }
789 
790         return scmChanges;
791     }
792 
793     private static List<Map<String, String>> getChangeFiles( List<ChangeFile> changeFiles )
794     {
795         List<Map<String, String>> files = new ArrayList<Map<String, String>>();
796 
797         if ( changeFiles != null )
798         {
799             for ( ChangeFile file : changeFiles )
800             {
801                 Map<String, String> changeFile = new HashMap<String, String>();
802                 if ( StringUtils.isNotEmpty( file.getName() ) )
803                 {
804                     changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_NAME, file.getName() );
805                 }
806                 else
807                 {
808                     changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_NAME, "" );
809                 }
810                 if ( StringUtils.isNotEmpty( file.getRevision() ) )
811                 {
812                     changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_REVISION, file.getRevision() );
813                 }
814                 else
815                 {
816                     changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_REVISION, "" );
817                 }
818                 if ( StringUtils.isNotEmpty( file.getStatus() ) )
819                 {
820                     changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_STATUS, file.getStatus() );
821                 }
822                 else
823                 {
824                     changeFile.put( ContinuumBuildAgentUtil.KEY_CHANGEFILE_STATUS, "" );
825                 }
826 
827                 files.add( changeFile );
828             }
829         }
830 
831         return files;
832     }
833 
834     public static List<File> getFiles( String userDirectory, File workingDirectory )
835         throws ContinuumException
836     {
837         return getFiles( workingDirectory, null, userDirectory );
838     }
839 
840     private static List<File> getFiles( File baseDirectory, String currentSubDirectory, String userDirectory )
841     {
842         List<File> dirs = new ArrayList<File>();
843 
844         File workingDirectory;
845 
846         if ( currentSubDirectory != null )
847         {
848             workingDirectory = new File( baseDirectory, currentSubDirectory );
849         }
850         else
851         {
852             workingDirectory = baseDirectory;
853         }
854 
855         String[] files = workingDirectory.list();
856 
857         if ( files != null )
858         {
859             for ( String file : files )
860             {
861                 File current = new File( workingDirectory, file );
862 
863                 String currentFile;
864 
865                 if ( currentSubDirectory == null )
866                 {
867                     currentFile = file;
868                 }
869                 else
870                 {
871                     currentFile = currentSubDirectory + "/" + file;
872                 }
873 
874                 if ( userDirectory != null && current.isDirectory() && userDirectory.startsWith( currentFile ) )
875                 {
876                     dirs.add( current );
877 
878                     dirs.addAll( getFiles( baseDirectory, currentFile, userDirectory ) );
879                 }
880                 else
881                 {
882                     dirs.add( current );
883                 }
884             }
885         }
886 
887         return dirs;
888     }
889 }