001package org.apache.maven.scm.provider.synergy.util;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.File;
023import java.io.IOException;
024import java.text.SimpleDateFormat;
025import java.util.ArrayList;
026import java.util.Date;
027import java.util.List;
028import java.util.Locale;
029
030import org.apache.maven.scm.ChangeFile;
031import org.apache.maven.scm.ScmException;
032import org.apache.maven.scm.ScmVersion;
033import org.apache.maven.scm.log.ScmLogger;
034import org.apache.maven.scm.provider.synergy.consumer.SynergyCreateTaskConsumer;
035import org.apache.maven.scm.provider.synergy.consumer.SynergyGetCompletedTasksConsumer;
036import org.apache.maven.scm.provider.synergy.consumer.SynergyGetTaskObjectsConsumer;
037import org.apache.maven.scm.provider.synergy.consumer.SynergyGetWorkingFilesConsumer;
038import org.apache.maven.scm.provider.synergy.consumer.SynergyGetWorkingProjectConsumer;
039import org.apache.maven.scm.provider.synergy.consumer.SynergyShowDefaultTaskConsumer;
040import org.apache.maven.scm.provider.synergy.consumer.SynergyWorkareaConsumer;
041import org.codehaus.plexus.util.cli.CommandLineException;
042import org.codehaus.plexus.util.cli.CommandLineUtils;
043import org.codehaus.plexus.util.cli.CommandLineUtils.StringStreamConsumer;
044import org.codehaus.plexus.util.cli.Commandline;
045import org.codehaus.plexus.util.cli.StreamConsumer;
046
047/**
048 * This class contains functional methods for Synergy.
049 *
050 * @author <a href="mailto:julien.henry@capgemini.com">Julien Henry</a>
051 * @author Olivier Lamy
052 *
053 */
054public final class SynergyUtil
055{
056
057    private SynergyUtil()
058    {
059    }
060
061    /**
062     * Separator used with formatted result
063     */
064    public static final String SEPARATOR = "#####";
065
066    /**
067     * Remove prefix path from a path. Example: removeParent("c:\tmp",
068     * "c:\tmp\foo.bar") returns "foo.bar"
069     *
070     * @param prefix parent path (prefix).
071     * @param file   file path.
072     * @return suffix
073     * @throws ScmException if parent is not a prefix of file
074     */
075    public static String removePrefix( File prefix, File file )
076        throws ScmException
077    {
078        try
079        {
080            String prefixStr = prefix.getCanonicalPath();
081            String fileStr = file.getCanonicalPath();
082            if ( !fileStr.startsWith( prefixStr ) )
083            {
084                throw new ScmException( prefixStr + " is not a prefix of " + fileStr );
085            }
086            return fileStr.substring( prefixStr.length() );
087        }
088        catch ( IOException e )
089        {
090            throw new ScmException( "IOException", e );
091        }
092
093    }
094
095    /**
096     * Get a working project whose predecessor is given.
097     *
098     * @param logger       a logger.
099     * @param projectSpec predecessor (prep project)
100     * @param username     owner of working project
101     * @param ccmAddr      Synergy session ID.
102     * @return projectSpec of the working checkout, or null if none
103     */
104    public static String getWorkingProject( ScmLogger logger, String projectSpec, String username, String ccmAddr )
105        throws ScmException
106    {
107        if ( logger.isDebugEnabled() )
108        {
109            logger.debug( "Synergy : Entering getWorkingProject method" );
110        }
111
112        String query =
113            "owner='" + username + "' and status='working' and type='project' and has_predecessor('" + projectSpec + "')";
114                //+ ":project:1')"; SCM-261
115
116        Commandline cl = SynergyCCM.query( query, "%objectname", ccmAddr );
117
118        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
119        SynergyGetWorkingProjectConsumer stdout = new SynergyGetWorkingProjectConsumer( logger );
120
121        int errorCode = executeSynergyCommand( logger, cl, stderr, stdout, false );
122
123        if ( logger.isDebugEnabled() )
124        {
125            logger.debug( "Synergy : getWorkingProject returns " + stdout.getProjectSpec() + " with code "
126                + errorCode );
127        }
128
129        return stdout.getProjectSpec();
130    }
131
132    /**
133     * Get working file(s) in a given project.
134     *
135     * @param logger       a logger.
136     * @param projectSpec (project)
137     * @param release      release
138     * @param ccmAddr      Synergy session ID.
139     * @return list of working files.
140     */
141    public static List<String> getWorkingFiles( ScmLogger logger, String projectSpec, String release, String ccmAddr )
142        throws ScmException
143    {
144        if ( logger.isDebugEnabled() )
145        {
146            logger.debug( "Synergy : Entering getWorkingFiles method" );
147        }
148
149        String query = "status='working' and release='" + release + "' and is_member_of('" + projectSpec + "')";
150
151        Commandline cl = SynergyCCM.query( query, SynergyGetWorkingFilesConsumer.OUTPUT_FORMAT, ccmAddr );
152
153        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
154        SynergyGetWorkingFilesConsumer stdout = new SynergyGetWorkingFilesConsumer( logger );
155
156        int errorCode = executeSynergyCommand( logger, cl, stderr, stdout, false );
157
158        if ( logger.isDebugEnabled() )
159        {
160            logger.debug( "Synergy : getWorkingFiles returns " + stdout.getFiles().size() + " files with code "
161                + errorCode );
162        }
163
164        return stdout.getFiles();
165    }
166
167    /**
168     * Populate the object list of a Modification by querying for objects
169     * associated with the task.
170     *
171     * @param logger  a logger.
172     * @param numTask task number.
173     * @param ccmAddr Synergy session ID.
174     */
175    public static List<ChangeFile> getModifiedObjects( ScmLogger logger, int numTask, String ccmAddr )
176        throws ScmException
177    {
178        if ( logger.isDebugEnabled() )
179        {
180            logger.debug( "Synergy : Entering getModifiedObjects method" );
181        }
182
183        Commandline cl = SynergyCCM.showTaskObjects( numTask, SynergyGetTaskObjectsConsumer.OUTPUT_FORMAT, ccmAddr );
184
185        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
186        SynergyGetTaskObjectsConsumer stdout = new SynergyGetTaskObjectsConsumer( logger );
187        int errorCode = executeSynergyCommand( logger, cl, stderr, stdout, false );
188
189        if ( logger.isDebugEnabled() )
190        {
191            logger.debug( "Synergy : getModifiedObjects returns " + stdout.getFiles().size() + " files with code "
192                + errorCode );
193        }
194
195        return stdout.getFiles();
196
197    }
198
199    /**
200     * Get a list of all tasks which are contained in all folders in the
201     * reconfigure properties of the specified project and were completed after
202     * startDate and before endDate.
203     *
204     * @param logger      a logger.
205     * @param projectSpec projectSpec.
206     * @param startDate   start date.
207     * @param endDate     end date.
208     * @param ccmAddr     Synergy session ID.
209     * @return A list of  {@link SynergyTask}
210     */
211    public static List<SynergyTask> getCompletedTasks( ScmLogger logger, String projectSpec, Date startDate, Date endDate,
212                                          String ccmAddr )
213        throws ScmException
214    {
215        if ( logger.isDebugEnabled() )
216        {
217            logger.debug( "Synergy : Entering getCompletedTasks method" );
218        }
219
220        // The format used for converting Java dates into CM Synergy dates
221        // Note that the format used to submit commands differs from the
222        // format used in the results of that command!?!
223        SimpleDateFormat toCcmDate = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss", new Locale( "en", "US" ) );
224
225        // Construct the query string
226        String query = "is_task_in_folder_of(is_folder_in_rp_of('" + projectSpec + "'))";
227        if ( startDate != null )
228        {
229            query = query + "and completion_date>time('" + toCcmDate.format( startDate ) + "')";
230        }
231        if ( endDate != null )
232        {
233            query = query + "and completion_date<time('" + toCcmDate.format( endDate ) + "')";
234        }
235
236        Commandline cl = SynergyCCM.query( query, SynergyGetCompletedTasksConsumer.OUTPUT_FORMAT, ccmAddr );
237
238        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
239        SynergyGetCompletedTasksConsumer stdout = new SynergyGetCompletedTasksConsumer( logger );
240
241        executeSynergyCommand( logger, cl, stderr, stdout, false );
242
243        if ( logger.isDebugEnabled() )
244        {
245            logger.debug( "Synergy : getCompletedTasks method returns " + stdout.getTasks().size() + " tasks" );
246        }
247
248        return stdout.getTasks();
249    }
250
251    /**
252     * Create a baseline.
253     *
254     * @param logger      a logger.
255     * @param projectSpec the projectSpec.
256     * @param name        name of the baseline.
257     * @param release     the release.
258     * @param purpose     the purpose.
259     * @param ccmAddr     used to run in multi-session.
260     * @throws ScmException
261     */
262    public static void createBaseline( ScmLogger logger, String projectSpec, String name, String release,
263                                       String purpose, String ccmAddr )
264        throws ScmException
265    {
266        if ( logger.isDebugEnabled() )
267        {
268            logger.debug( "Synergy : Entering createBaseline method" );
269        }
270
271        Commandline cl = SynergyCCM.createBaseline( projectSpec, name, release, purpose, ccmAddr );
272
273        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
274        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
275
276        executeSynergyCommand( logger, cl, stderr, stdout, true );
277    }
278
279    /**
280     * Add new file to Synergy database.
281     *
282     * @param logger  a logger.
283     * @param file    file to be added.
284     * @param message log message for Synergy.
285     * @param ccmAddr used to run in multi-session.
286     * @throws ScmException
287     */
288    public static void create( ScmLogger logger, File file, String message, String ccmAddr )
289        throws ScmException
290    {
291        if ( logger.isDebugEnabled() )
292        {
293            logger.debug( "Synergy : Entering create method" );
294        }
295
296        List<File> files = new ArrayList<File>();
297        files.add( file );
298        Commandline cl = SynergyCCM.create( files, message, ccmAddr );
299
300        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
301        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
302
303        executeSynergyCommand( logger, cl, stderr, stdout, true );
304    }
305
306    /**
307     * Create new task.
308     *
309     * @param logger      a logger.
310     * @param synopsis    short description of task.
311     * @param release     release.
312     * @param defaultTask should this task become the default task?
313     * @param ccmAddr     used to run in multi-session.
314     * @return Task number
315     * @throws ScmException
316     */
317    public static int createTask( ScmLogger logger, String synopsis, String release, boolean defaultTask,
318                                  String ccmAddr )
319        throws ScmException
320    {
321        if ( logger.isDebugEnabled() )
322        {
323            logger.debug( "Synergy : Entering createTask method of SynergyUtil" );
324        }
325
326        if ( synopsis == null || synopsis.equals( "" ) )
327        {
328            throw new ScmException( "A synopsis must be specified to create a task." );
329        }
330
331        Commandline cl = SynergyCCM.createTask( synopsis, release, defaultTask, ccmAddr );
332
333        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
334        SynergyCreateTaskConsumer stdout = new SynergyCreateTaskConsumer( logger );
335
336        executeSynergyCommand( logger, cl, stderr, stdout, true );
337
338        if ( logger.isDebugEnabled() )
339        {
340            logger.debug( "createTask returns " + stdout.getTask() );
341        }
342
343        return stdout.getTask();
344    }
345
346    /**
347     * Checkin the default task.
348     *
349     * @param logger  a logger.
350     * @param comment a comment.
351     * @param ccmAddr Synergy session ID.
352     * @throws ScmException
353     */
354    public static void checkinDefaultTask( ScmLogger logger, String comment, String ccmAddr )
355        throws ScmException
356    {
357        if ( logger.isDebugEnabled() )
358        {
359            logger.debug( "Synergy : Entering checkinDefaultTask method" );
360        }
361
362        Commandline cl = SynergyCCM.checkinTask( "default", comment, ccmAddr );
363
364        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
365        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
366
367        executeSynergyCommand( logger, cl, stderr, stdout, true );
368    }
369
370    /**
371     * Checkin a task.
372     *
373     * @param logger     a logger.
374     * @param taskNumber task number.
375     * @param comment    a comment.
376     * @param ccmAddr    Synergy session ID.
377     * @throws ScmException
378     */
379    public static void checkinTask( ScmLogger logger, int taskNumber, String comment, String ccmAddr )
380        throws ScmException
381    {
382        if ( logger.isDebugEnabled() )
383        {
384            logger.debug( "Synergy : Entering checkinTask method" );
385        }
386
387        Commandline cl = SynergyCCM.checkinTask( "" + taskNumber, comment, ccmAddr );
388
389        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
390        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
391
392        executeSynergyCommand( logger, cl, stderr, stdout, true );
393    }
394
395    /**
396     * Delete file from Synergy database.
397     *
398     * @param logger  a logger.
399     * @param file    file to be deleted.
400     * @param ccmAddr used to run in multi-session.
401     * @throws ScmException
402     */
403    public static void delete( ScmLogger logger, File file, String ccmAddr, boolean replace )
404        throws ScmException
405    {
406        if ( logger.isDebugEnabled() )
407        {
408            logger.debug( "Synergy : Entering delete method" );
409        }
410
411        List<File> list = new ArrayList<File>();
412        list.add( file );
413
414        Commandline cl = SynergyCCM.delete( list, ccmAddr, replace );
415
416        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
417        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
418
419        executeSynergyCommand( logger, cl, stderr, stdout, true );
420    }
421
422    /**
423     * Reconfigure a project.
424     *
425     * @param logger       a logger.
426     * @param projectSpec projectSpec (i.e. myProject~1).
427     * @param ccmAddr      used to run in multi-session.
428     * @throws ScmException
429     */
430    public static void reconfigure( ScmLogger logger, String projectSpec, String ccmAddr )
431        throws ScmException
432    {
433        if ( logger.isDebugEnabled() )
434        {
435            logger.debug( "Synergy : Entering reconfigure method" );
436        }
437        Commandline cl = SynergyCCM.reconfigure( projectSpec, ccmAddr );
438
439        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
440        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
441
442        executeSynergyCommand( logger, cl, stderr, stdout, true );
443    }
444
445    /**
446     * Reconfigure properties of a project.
447     *
448     * @param logger       a logger.
449     * @param projectSpec projectSpec (i.e. myProject~1).
450     * @param ccmAddr      used to run in multi-session.
451     * @throws ScmException
452     */
453    public static void reconfigureProperties( ScmLogger logger, String projectSpec, String ccmAddr )
454        throws ScmException
455    {
456        if ( logger.isDebugEnabled() )
457        {
458            logger.debug( "Synergy : Entering reconfigureProperties method" );
459        }
460        Commandline cl = SynergyCCM.reconfigureProperties( projectSpec, ccmAddr );
461
462        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
463        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
464
465        executeSynergyCommand( logger, cl, stderr, stdout, true );
466    }
467
468    /**
469     * Reconcile a project with -uwa option.
470     *
471     * @param logger       a logger.
472     * @param projectSpec projectSpec (i.e. myProject~1).
473     * @param ccmAddr      used to run in multi-session.
474     * @throws ScmException
475     */
476    public static void reconcileUwa( ScmLogger logger, String projectSpec, String ccmAddr )
477        throws ScmException
478    {
479        if ( logger.isDebugEnabled() )
480        {
481            logger.debug( "Synergy : Entering reconcileUwa method" );
482        }
483        Commandline cl = SynergyCCM.reconcileUwa( projectSpec, ccmAddr );
484
485        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
486        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
487
488        executeSynergyCommand( logger, cl, stderr, stdout, true );
489    }
490
491    /**
492     * Reconcile a project with -udb option.
493     *
494     * @param logger       a logger.
495     * @param projectSpec projectSpec (i.e. myProject~1).
496     * @param ccmAddr      used to run in multi-session.
497     * @throws ScmException
498     */
499    public static void reconcileUdb( ScmLogger logger, String projectSpec, String ccmAddr )
500        throws ScmException
501    {
502        if ( logger.isDebugEnabled() )
503        {
504            logger.debug( "Synergy : Entering reconcileUdb method" );
505        }
506        Commandline cl = SynergyCCM.reconcileUdb( projectSpec, ccmAddr );
507
508        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
509        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
510
511        executeSynergyCommand( logger, cl, stderr, stdout, true );
512    }
513
514    /**
515     * Checkout given files or directory.
516     *
517     * @param logger  a logger.
518     * @param files   files to add.
519     * @param ccmAddr Synergy session ID.
520     * @throws ScmException
521     */
522    public static void checkoutFiles( ScmLogger logger, List<File> files, String ccmAddr )
523        throws ScmException
524    {
525        if ( logger.isDebugEnabled() )
526        {
527            logger.debug( "Synergy : Entering checkoutFiles files method" );
528        }
529
530        Commandline cl = SynergyCCM.checkoutFiles( files, ccmAddr );
531
532        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
533        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
534
535        executeSynergyCommand( logger, cl, stderr, stdout, true );
536    }
537
538    /**
539     * Checkout a given project.
540     *
541     * @param logger       a logger.
542     * @param directory    new project work area, or null if you want to use default wa.
543     * @param projectSpec projectSpec (i.e. myProject~1).
544     * @param ccmAddr      used to run in multi-session.
545     * @return checkout directory (directory + new project spec)
546     * @throws ScmException
547     */
548    public static void checkoutProject( ScmLogger logger, File directory, String projectSpec, ScmVersion version,
549                                        String purpose, String release, String ccmAddr )
550        throws ScmException
551    {
552        if ( logger.isDebugEnabled() )
553        {
554            logger.debug( "Synergy : Entering checkoutProject project method" );
555        }
556
557        Commandline cl = SynergyCCM.checkoutProject( directory, projectSpec, version, purpose, release, ccmAddr );
558
559        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
560        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
561
562        executeSynergyCommand( logger, cl, stderr, stdout, true );
563
564    }
565
566    /**
567     * Checkin a given project.
568     *
569     * @param logger       a logger.
570     * @param projectSpec projectSpec (i.e. myProject~1).
571     * @param comment      message.
572     * @param ccmAddr      used to run in multi-session.
573     * @return checkout directory (directory + new project spec)
574     * @throws ScmException
575     */
576    public static void checkinProject( ScmLogger logger, String projectSpec, String comment, String ccmAddr )
577        throws ScmException
578    {
579        if ( logger.isDebugEnabled() )
580        {
581            logger.debug( "Synergy : Entering checkinProject project method" );
582        }
583
584        Commandline cl = SynergyCCM.checkinProject( projectSpec, comment, ccmAddr );
585
586        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
587        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
588
589        executeSynergyCommand( logger, cl, stderr, stdout, true );
590
591    }
592
593    /**
594     * Checkin a file set.
595     *
596     * @param logger  a logger.
597     * @param ccmAddr used to run in multi-session.
598     * @return checkout directory (directory + new project spec)
599     * @throws ScmException
600     */
601    public static void checkinFiles( ScmLogger logger, List<File> files, String comment, String ccmAddr )
602        throws ScmException
603    {
604        if ( logger.isDebugEnabled() )
605        {
606            logger.debug( "Synergy : Entering checkinFiles project method" );
607        }
608
609        Commandline cl = SynergyCCM.checkinFiles( files, comment, ccmAddr );
610
611        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
612        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
613
614        executeSynergyCommand( logger, cl, stderr, stdout, true );
615
616    }
617    
618    /**
619     * Get the number of the current (ie default) task.
620     * 
621     * @param logger  a logger.
622     * @param ccmAddr current Synergy session id.
623     * @return the number of the current (ie default) task. 0 if current task 
624     *             is not set.
625     * @throws ScmException
626     */
627    public static int getDefaultTask( ScmLogger logger, String ccmAddr )
628        throws ScmException
629    {
630        if ( logger.isDebugEnabled() )
631        {
632            logger.debug( "Synergy : Entering getDefaultTask method" );
633        }
634
635        Commandline cl = SynergyCCM.showDefaultTask( ccmAddr );
636
637        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
638        SynergyShowDefaultTaskConsumer stdout = new SynergyShowDefaultTaskConsumer(logger);
639
640        int errorCode = executeSynergyCommand( logger, cl, stderr, stdout, false );
641
642        if ( logger.isDebugEnabled() )
643        {
644            logger.debug( "getDefaultTask returns " + stdout.getTask() + " with error code " + errorCode );
645        }
646
647        return stdout.getTask();
648    }
649    
650    /**
651     * Set the current (ie default) task.
652     * 
653     * @param logger  a logger.
654     * @param task        the number of the task to set as current task. 
655     * @param ccmAddr current Synergy session id.
656     * @throws ScmException
657     */
658    public static void setDefaultTask( ScmLogger logger, int task, String ccmAddr )
659        throws ScmException
660    {
661        if ( logger.isDebugEnabled() )
662        {
663            logger.debug( "Synergy : Entering setDefaultTask method" );
664        }
665
666        Commandline cl = SynergyCCM.setDefaultTask( task, ccmAddr );
667
668        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
669        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
670
671        executeSynergyCommand( logger, cl, stderr, stdout, true );
672    }
673
674    /**
675     * Synchronize a given project.
676     *
677     * @param logger       a logger.
678     * @param projectSpec projectSpec (i.e. myProject~1).
679     * @param ccmAddr      used to run in multi-session.
680     * @throws ScmException
681     */
682    public static void synchronize( ScmLogger logger, String projectSpec, String ccmAddr )
683        throws ScmException
684    {
685        if ( logger.isDebugEnabled() )
686        {
687            logger.debug( "Synergy : Entering synchronize method" );
688        }
689
690        Commandline cl = SynergyCCM.synchronize( projectSpec, ccmAddr );
691
692        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
693        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
694
695        executeSynergyCommand( logger, cl, stderr, stdout, true );
696    }
697
698    /**
699     * Get the work area of a given project.
700     *
701     * @param logger       a logger.
702     * @param projectSpec projectSpec (i.e. myProject~1).
703     * @param ccmAddr      used to run in multi-session.
704     * @throws ScmException
705     */
706    public static File getWorkArea( ScmLogger logger, String projectSpec, String ccmAddr )
707        throws ScmException
708    {
709        if ( logger.isDebugEnabled() )
710        {
711            logger.debug( "Synergy : Entering getWorkArea method" );
712        }
713
714        Commandline cl = SynergyCCM.showWorkArea( projectSpec, ccmAddr );
715
716        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
717        SynergyWorkareaConsumer stdout = new SynergyWorkareaConsumer( logger );
718
719        executeSynergyCommand( logger, cl, stderr, stdout, true );
720
721        if ( logger.isDebugEnabled() )
722        {
723            logger.debug( "Synergy : getWorkArea returns " + stdout.getWorkAreaPath() );
724        }
725
726        return stdout.getWorkAreaPath();
727    }
728
729    /**
730     * Stop a ccm session.
731     *
732     * @param logger  a logger.
733     * @param ccmAddr used to run in multi-session.
734     * @throws ScmException
735     */
736    public static void stop( ScmLogger logger, String ccmAddr )
737        throws ScmException
738    {
739        if ( logger.isDebugEnabled() )
740        {
741            logger.debug( "Synergy : Entering stop method" );
742        }
743        Commandline cl = SynergyCCM.stop( ccmAddr );
744
745        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
746        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
747
748        executeSynergyCommand( logger, cl, stderr, stdout, true );
749    }
750
751    /**
752     * Start a session Synergy
753     *
754     * @param logger   a logger.
755     * @param username username.
756     * @param password password.
757     * @param role     role or null if none.
758     * @return ccmAddr value to use with this session.
759     */
760    public static String start( ScmLogger logger, String username, String password, SynergyRole role )
761        throws ScmException
762    {
763        if ( logger.isDebugEnabled() )
764        {
765            logger.debug( "Synergy : Entering start method" );
766        }
767
768        if ( username == null )
769        {
770            throw new ScmException( "username can't be null" );
771        }
772
773        if ( password == null )
774        {
775            throw new ScmException( "password can't be null" );
776        }
777
778        Commandline cl = SynergyCCM.start( username, password, role );
779
780        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
781        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
782
783        //executeSynergyCommand( logger, cl, stderr, stdout, true );
784                
785        int exitCode = executeSynergyCommand( logger, cl, stderr, stdout, false );
786                
787        if ( logger.isDebugEnabled() )
788        {
789            logger.debug( "Synergy : start returns with error code " + exitCode );
790        }               
791                
792        if ( exitCode != 0 ) 
793        {
794            cl = SynergyCCM.startRemote( username, password, role );
795            
796            stderr = new CommandLineUtils.StringStreamConsumer();
797            stdout = new CommandLineUtils.StringStreamConsumer();                       
798            
799            executeSynergyCommand( logger, cl, stderr, stdout, true );                  
800        }
801
802        return stdout.getOutput();
803    }
804
805    /**
806     * Get Database delimiter
807     *
808     * @param logger  a logger.
809     * @param ccmAddr Synergy session ID.
810     * @return delimiter of the database (i.e. ~).
811     */
812    public static String delimiter( ScmLogger logger, String ccmAddr )
813        throws ScmException
814    {
815        if ( logger.isDebugEnabled() )
816        {
817            logger.debug( "Synergy : Entering delimiter method" );
818        }
819
820        Commandline cl = SynergyCCM.delimiter( ccmAddr );
821
822        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
823        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
824
825        executeSynergyCommand( logger, cl, stderr, stdout, true );
826
827        return stdout.getOutput();
828    }
829
830    /**
831     * Execute a command line for Synergy.
832     *
833     * @param logger      a logger.
834     * @param cl          command line.
835     * @param stderr      stderr.
836     * @param stdout      stdout.
837     * @param failOnError should we raise an exception when exit code != 0
838     * @return exit code.
839     * @throws ScmException on error or if exit code != 0 and failOnError = true
840     */
841    protected static int executeSynergyCommand( ScmLogger logger, Commandline cl, StringStreamConsumer stderr,
842                                                StreamConsumer stdout, boolean failOnError )
843        throws ScmException
844    {
845        int exitCode;
846
847        try
848        {
849            if ( logger.isDebugEnabled() )
850            {
851                logger.debug( "Executing: " + cl.toString() );
852            }
853            exitCode = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
854        }
855        catch ( CommandLineException ex )
856        {
857            throw new ScmException( "Error while executing synergy command [" + cl.toString() + "].", ex );
858        }
859
860        if ( logger.isDebugEnabled() )
861        {
862            logger.debug( "Exit code :" + exitCode );
863        }
864        if ( stdout instanceof StringStreamConsumer )
865        {
866            if ( logger.isDebugEnabled() )
867            {
868                logger.debug( "STDOUT :" + ( (StringStreamConsumer) stdout ).getOutput() );
869            }
870        }
871        else
872        {
873            if ( logger.isDebugEnabled() )
874            {
875                logger.debug( "STDOUT : unavailable" );
876            }
877        }
878        if ( logger.isDebugEnabled() )
879        {
880            logger.debug( "STDERR :" + stderr.getOutput() );
881        }
882
883        if ( exitCode != 0 && failOnError )
884        {
885            if ( stdout instanceof StringStreamConsumer )
886            {
887                throw new ScmException( "Commandeline = " + cl.toString() + "\nSTDOUT = "
888                    + ( (StringStreamConsumer) stdout ).getOutput() + "\nSTDERR = " + stderr.getOutput() + "\n" );
889            }
890            else
891            {
892                throw new ScmException( "Commandeline = " + cl.toString() + "\nSTDOUT = unavailable" + "\nSTDERR = "
893                    + stderr.getOutput() + "\n" );
894            }
895        }
896
897        return exitCode;
898    }
899
900}