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