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     * @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     * @throws ScmException
574     */
575    public static void checkinProject( ScmLogger logger, String projectSpec, String comment, String ccmAddr )
576        throws ScmException
577    {
578        if ( logger.isDebugEnabled() )
579        {
580            logger.debug( "Synergy : Entering checkinProject project method" );
581        }
582
583        Commandline cl = SynergyCCM.checkinProject( projectSpec, comment, ccmAddr );
584
585        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
586        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
587
588        executeSynergyCommand( logger, cl, stderr, stdout, true );
589
590    }
591
592    /**
593     * Checkin a file set.
594     *
595     * @param logger  a logger.
596     * @param ccmAddr used to run in multi-session.
597     * @throws ScmException
598     */
599    public static void checkinFiles( ScmLogger logger, List<File> files, String comment, String ccmAddr )
600        throws ScmException
601    {
602        if ( logger.isDebugEnabled() )
603        {
604            logger.debug( "Synergy : Entering checkinFiles project method" );
605        }
606
607        Commandline cl = SynergyCCM.checkinFiles( files, comment, ccmAddr );
608
609        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
610        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
611
612        executeSynergyCommand( logger, cl, stderr, stdout, true );
613
614    }
615    
616    /**
617     * Get the number of the current (ie default) task.
618     * 
619     * @param logger  a logger.
620     * @param ccmAddr current Synergy session id.
621     * @return the number of the current (ie default) task. 0 if current task 
622     *            is not set.
623     * @throws ScmException
624     */
625    public static int getDefaultTask( ScmLogger logger, String ccmAddr )
626        throws ScmException
627    {
628        if ( logger.isDebugEnabled() )
629        {
630            logger.debug( "Synergy : Entering getDefaultTask method" );
631        }
632
633        Commandline cl = SynergyCCM.showDefaultTask( ccmAddr );
634
635        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
636        SynergyShowDefaultTaskConsumer stdout = new SynergyShowDefaultTaskConsumer( logger );
637
638        int errorCode = executeSynergyCommand( logger, cl, stderr, stdout, false );
639
640        if ( logger.isDebugEnabled() )
641        {
642            logger.debug( "getDefaultTask returns " + stdout.getTask() + " with error code " + errorCode );
643        }
644
645        return stdout.getTask();
646    }
647
648    /**
649     * Set the current (ie default) task.
650     * 
651     * @param logger  a logger.
652     * @param task      the number of the task to set as current task. 
653     * @param ccmAddr current Synergy session id.
654     * @throws ScmException
655     */
656    public static void setDefaultTask( ScmLogger logger, int task, String ccmAddr )
657        throws ScmException
658    {
659        if ( logger.isDebugEnabled() )
660        {
661            logger.debug( "Synergy : Entering setDefaultTask method" );
662        }
663
664        Commandline cl = SynergyCCM.setDefaultTask( task, ccmAddr );
665
666        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
667        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
668
669        executeSynergyCommand( logger, cl, stderr, stdout, true );
670    }
671
672    /**
673     * Synchronize a given project.
674     *
675     * @param logger       a logger.
676     * @param projectSpec projectSpec (i.e. myProject~1).
677     * @param ccmAddr      used to run in multi-session.
678     * @throws ScmException
679     */
680    public static void synchronize( ScmLogger logger, String projectSpec, String ccmAddr )
681        throws ScmException
682    {
683        if ( logger.isDebugEnabled() )
684        {
685            logger.debug( "Synergy : Entering synchronize method" );
686        }
687
688        Commandline cl = SynergyCCM.synchronize( projectSpec, ccmAddr );
689
690        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
691        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
692
693        executeSynergyCommand( logger, cl, stderr, stdout, true );
694    }
695
696    /**
697     * Get the work area of a given project.
698     *
699     * @param logger       a logger.
700     * @param projectSpec projectSpec (i.e. myProject~1).
701     * @param ccmAddr      used to run in multi-session.
702     * @throws ScmException
703     */
704    public static File getWorkArea( ScmLogger logger, String projectSpec, String ccmAddr )
705        throws ScmException
706    {
707        if ( logger.isDebugEnabled() )
708        {
709            logger.debug( "Synergy : Entering getWorkArea method" );
710        }
711
712        Commandline cl = SynergyCCM.showWorkArea( projectSpec, ccmAddr );
713
714        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
715        SynergyWorkareaConsumer stdout = new SynergyWorkareaConsumer( logger );
716
717        executeSynergyCommand( logger, cl, stderr, stdout, true );
718
719        if ( logger.isDebugEnabled() )
720        {
721            logger.debug( "Synergy : getWorkArea returns " + stdout.getWorkAreaPath() );
722        }
723
724        return stdout.getWorkAreaPath();
725    }
726
727    /**
728     * Stop a ccm session.
729     *
730     * @param logger  a logger.
731     * @param ccmAddr used to run in multi-session.
732     * @throws ScmException
733     */
734    public static void stop( ScmLogger logger, String ccmAddr )
735        throws ScmException
736    {
737        if ( logger.isDebugEnabled() )
738        {
739            logger.debug( "Synergy : Entering stop method" );
740        }
741        Commandline cl = SynergyCCM.stop( ccmAddr );
742
743        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
744        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
745
746        executeSynergyCommand( logger, cl, stderr, stdout, true );
747    }
748
749    /**
750     * Start a session Synergy
751     *
752     * @param logger   a logger.
753     * @param username username.
754     * @param password password.
755     * @param role     role or null if none.
756     * @return ccmAddr value to use with this session.
757     */
758    public static String start( ScmLogger logger, String username, String password, SynergyRole role )
759        throws ScmException
760    {
761        if ( logger.isDebugEnabled() )
762        {
763            logger.debug( "Synergy : Entering start method" );
764        }
765
766        if ( username == null )
767        {
768            throw new ScmException( "username can't be null" );
769        }
770
771        if ( password == null )
772        {
773            throw new ScmException( "password can't be null" );
774        }
775
776        Commandline cl = SynergyCCM.start( username, password, role );
777
778        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
779        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
780
781        //executeSynergyCommand( logger, cl, stderr, stdout, true );
782        
783        int exitCode = executeSynergyCommand( logger, cl, stderr, stdout, false );
784        
785        if ( logger.isDebugEnabled() )
786        {
787            logger.debug( "Synergy : start returns with error code " + exitCode );
788        }        
789        
790        if ( exitCode != 0 )
791        {
792            cl = SynergyCCM.startRemote( username, password, role );
793
794            stderr = new CommandLineUtils.StringStreamConsumer();
795            stdout = new CommandLineUtils.StringStreamConsumer();
796
797            executeSynergyCommand( logger, cl, stderr, stdout, true );
798        }
799
800        return stdout.getOutput();
801    }
802
803    /**
804     * Get Database delimiter
805     *
806     * @param logger  a logger.
807     * @param ccmAddr Synergy session ID.
808     * @return delimiter of the database (i.e. ~).
809     */
810    public static String delimiter( ScmLogger logger, String ccmAddr )
811        throws ScmException
812    {
813        if ( logger.isDebugEnabled() )
814        {
815            logger.debug( "Synergy : Entering delimiter method" );
816        }
817
818        Commandline cl = SynergyCCM.delimiter( ccmAddr );
819
820        CommandLineUtils.StringStreamConsumer stderr = new CommandLineUtils.StringStreamConsumer();
821        CommandLineUtils.StringStreamConsumer stdout = new CommandLineUtils.StringStreamConsumer();
822
823        executeSynergyCommand( logger, cl, stderr, stdout, true );
824
825        return stdout.getOutput();
826    }
827
828    /**
829     * Execute a command line for Synergy.
830     *
831     * @param logger      a logger.
832     * @param cl          command line.
833     * @param stderr      stderr.
834     * @param stdout      stdout.
835     * @param failOnError should we raise an exception when exit code != 0
836     * @return exit code.
837     * @throws ScmException on error or if exit code != 0 and failOnError = true
838     */
839    protected static int executeSynergyCommand( ScmLogger logger, Commandline cl, StringStreamConsumer stderr,
840                                                StreamConsumer stdout, boolean failOnError )
841        throws ScmException
842    {
843        int exitCode;
844
845        try
846        {
847            if ( logger.isDebugEnabled() )
848            {
849                logger.debug( "Executing: " + cl.toString() );
850            }
851            exitCode = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
852        }
853        catch ( CommandLineException ex )
854        {
855            throw new ScmException( "Error while executing synergy command [" + cl.toString() + "].", ex );
856        }
857
858        if ( logger.isDebugEnabled() )
859        {
860            logger.debug( "Exit code :" + exitCode );
861        }
862        if ( stdout instanceof StringStreamConsumer )
863        {
864            if ( logger.isDebugEnabled() )
865            {
866                logger.debug( "STDOUT :" + ( (StringStreamConsumer) stdout ).getOutput() );
867            }
868        }
869        else
870        {
871            if ( logger.isDebugEnabled() )
872            {
873                logger.debug( "STDOUT : unavailable" );
874            }
875        }
876        if ( logger.isDebugEnabled() )
877        {
878            logger.debug( "STDERR :" + stderr.getOutput() );
879        }
880
881        if ( exitCode != 0 && failOnError )
882        {
883            if ( stdout instanceof StringStreamConsumer )
884            {
885                throw new ScmException( "Commandeline = " + cl.toString() + "\nSTDOUT = "
886                    + ( (StringStreamConsumer) stdout ).getOutput() + "\nSTDERR = " + stderr.getOutput() + "\n" );
887            }
888            else
889            {
890                throw new ScmException( "Commandeline = " + cl.toString() + "\nSTDOUT = unavailable" + "\nSTDERR = "
891                    + stderr.getOutput() + "\n" );
892            }
893        }
894
895        return exitCode;
896    }
897
898}