001    package 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    
022    import org.apache.maven.scm.ScmException;
023    import org.apache.maven.scm.ScmVersion;
024    import org.codehaus.plexus.util.StringUtils;
025    import org.codehaus.plexus.util.cli.CommandLineUtils;
026    import org.codehaus.plexus.util.cli.Commandline;
027    
028    import java.io.File;
029    import java.io.IOException;
030    import java.util.Calendar;
031    import java.util.Iterator;
032    import java.util.List;
033    import java.util.Properties;
034    
035    /**
036     * This class contains methods to execute Synergy <code>ccm</code> command line.
037     *
038     * @author <a href="mailto:julien.henry@capgemini.com">Julien Henry</a>
039     * @version $Id: SynergyCCM.java 1333668 2012-05-03 22:37:08Z hboutemy $
040     */
041    public class SynergyCCM
042    {
043    
044        private static final String CCM = "ccm";
045    
046        private static final String BASELINE = "baseline";
047    
048        private static final String CI = "ci";
049    
050        private static final String CO = "co";
051    
052        private static final String CREATE = "create";
053    
054        private static final String DELETE = "delete";
055    
056        private static final String DELIMITER = "delimiter";
057    
058        private static final String DIR = "dir";
059    
060        private static final String QUERY = "query";
061    
062        private static final String RECONCILE = "rwa";
063    
064        private static final String RECONFIGURE = "reconfigure";
065    
066        private static final String RECONFIGURE_PROPERTIES = "reconfigure_properties";
067    
068        private static final String START = "start";
069    
070        private static final String STOP = "stop";
071    
072        private static final String SYNC = "sync";
073    
074        private static final String TASK = "task";
075    
076        private static final String WA = "wa";
077    
078        /**
079         * Create commandline for getting list of objects in a task.
080         *
081         * @param taskNumber Task number.
082         * @param format     Output format.
083         * @param ccmAddr
084         * @return the commandline.
085         * @throws ScmException
086         */
087        public static Commandline showTaskObjects( int taskNumber, String format, String ccmAddr )
088            throws ScmException
089        {
090            // Construct the CM Synergy command
091            Commandline cl = new Commandline();
092    
093            configureEnvironment( cl, ccmAddr );
094    
095            cl.setExecutable( CCM );
096    
097            cl.createArg().setValue( TASK );
098            cl.createArg().setValue( "-show" );
099            cl.createArg().setValue( "objects" );
100    
101            // Set up the output format
102            if ( format != null && !format.equals( "" ) )
103            {
104                cl.createArg().setValue( "-f" );
105                cl.createArg().setValue( format );
106            }
107    
108            cl.createArg().setValue( Integer.toString( taskNumber ) );
109    
110            return cl;
111        }
112    
113        /**
114         * Create commandline for query.
115         *
116         * @param query    query.
117         * @param format   Output format
118         * @param ccmAddr
119         * @return the command line.
120         * @throws ScmException
121         */
122        public static Commandline query( String query, String format, String ccmAddr )
123            throws ScmException
124        {
125    
126            // Construct the CM Synergy command
127            Commandline cl = new Commandline();
128    
129            configureEnvironment( cl, ccmAddr );
130    
131            cl.setExecutable( CCM );
132            cl.createArg().setValue( QUERY );
133    
134            cl.createArg().setValue( "-u" );
135    
136            // Set up the output format
137            if ( format != null && !format.equals( "" ) )
138            {
139                cl.createArg().setValue( "-f" );
140                cl.createArg().setValue( format );
141            }
142    
143            cl.createArg().setValue( query );
144    
145            return cl;
146        }
147    
148        /**
149         * Create command line for creating a baseline.
150         *
151         * @param projectSpec project_name~project_version
152         * @param name        Name of the baseline
153         * @param release     the release.
154         * @param purpose     the purpose.
155         * @param ccmAddr
156         * @return the command line.
157         * @throws ScmException
158         */
159        public static Commandline createBaseline( String projectSpec, String name, String release, String purpose,
160                                                  String ccmAddr )
161            throws ScmException
162        {
163            Commandline cl = new Commandline();
164    
165            configureEnvironment( cl, ccmAddr );
166    
167            cl.setExecutable( CCM );
168            cl.createArg().setValue( BASELINE );
169    
170            cl.createArg().setValue( "-create" );
171            cl.createArg().setValue( name );
172    
173            cl.createArg().setValue( "-p" );
174            cl.createArg().setValue( projectSpec );
175    
176            cl.createArg().setValue( "-release" );
177            cl.createArg().setValue( release );
178    
179            cl.createArg().setValue( "-purpose" );
180            cl.createArg().setValue( purpose );
181    
182            return cl;
183    
184        }
185    
186        /**
187         * Create command line for adding a fileset to a project
188         *
189         * @param files    fileset.
190         * @param message  message log, or null if none.
191         * @param ccmAddr
192         * @return the command line.
193         * @throws ScmException
194         */
195        public static Commandline create( List<File> files, String message, String ccmAddr )
196            throws ScmException
197        {
198            Commandline cl = new Commandline();
199    
200            configureEnvironment( cl, ccmAddr );
201    
202            cl.setExecutable( CCM );
203            cl.createArg().setValue( CREATE );
204    
205            if ( message != null && !message.equals( "" ) )
206            {
207    
208                cl.createArg().setValue( "-c" );
209    
210                cl.createArg().setValue( message );
211    
212            }
213    
214            for ( File f : files )
215            {
216                try
217                {
218                    cl.createArg().setValue( f.getCanonicalPath() );
219                }
220                catch ( IOException e )
221                {
222                    throw new ScmException( "Invalid file path " + f.toString(), e );
223                }
224            }
225    
226            return cl;
227    
228        }
229    
230        /**
231         * Create command line for creating a task
232         *
233         * @param synopsis    synopsis.
234         * @param release     release.
235         * @param defaultTask default.
236         * @param ccmAddr
237         * @return the command line.
238         * @throws ScmException
239         */
240        public static Commandline createTask( String synopsis, String release, boolean defaultTask, String ccmAddr )
241            throws ScmException
242        {
243            Commandline cl = new Commandline();
244    
245            configureEnvironment( cl, ccmAddr );
246    
247            cl.setExecutable( CCM );
248            cl.createArg().setValue( TASK );
249    
250            cl.createArg().setValue( "-create" );
251    
252            cl.createArg().setValue( "-synopsis" );
253            cl.createArg().setValue( synopsis );
254    
255            if ( release != null && !release.equals( "" ) )
256            {
257                cl.createArg().setValue( "-release" );
258                cl.createArg().setValue( release );
259            }
260    
261            if ( defaultTask )
262            {
263                cl.createArg().setValue( "-default" );
264            }
265    
266            cl.createArg().setValue( "-description" );
267            cl.createArg().setValue(
268                "This task was created by Maven SCM Synergy provider on " + Calendar.getInstance().getTime() );
269    
270            return cl;
271    
272        }
273    
274        /**
275         * Create command line for checkin a task
276         *
277         * @param taskSpecs task_specs or default
278         * @param comment    comment.
279         * @param ccmAddr
280         * @return
281         * @throws ScmException
282         */
283        public static Commandline checkinTask( String taskSpecs, String comment, String ccmAddr )
284            throws ScmException
285        {
286            Commandline cl = new Commandline();
287    
288            configureEnvironment( cl, ccmAddr );
289    
290            cl.setExecutable( CCM );
291            cl.createArg().setValue( TASK );
292    
293            cl.createArg().setValue( "-checkin" );
294    
295            cl.createArg().setValue( taskSpecs );
296    
297            cl.createArg().setValue( "-comment" );
298            cl.createArg().setValue( comment );
299    
300            return cl;
301    
302        }
303    
304        /**
305         * Create command line for deleting file(s).
306         *
307         * @param files    fileset.
308         * @param ccmAddr
309         * @param replace  replace with previous version of file ?
310         * @return
311         * @throws ScmException
312         */
313        public static Commandline delete( List<File> files, String ccmAddr, boolean replace )
314            throws ScmException
315        {
316            Commandline cl = new Commandline();
317    
318            configureEnvironment( cl, ccmAddr );
319    
320            cl.setExecutable( CCM );
321            cl.createArg().setValue( DELETE );
322    
323            if ( replace )
324            {
325                cl.createArg().setValue( "-replace" );
326            }
327    
328            for ( File f : files )
329            {
330                try
331                {
332                    cl.createArg().setValue( f.getCanonicalPath() );
333                }
334                catch ( IOException e )
335                {
336                    throw new ScmException( "Invalid file path " + f.toString(), e );
337                }
338            }
339    
340            return cl;
341    
342        }
343    
344        /**
345         * Create commandline to reconfigure a project.
346         *
347         * @param projectSpec
348         * @param ccmAddr
349         * @return the command line.
350         * @throws ScmException
351         */
352        public static Commandline reconfigure( String projectSpec, String ccmAddr )
353            throws ScmException
354        {
355            Commandline cl = new Commandline();
356    
357            configureEnvironment( cl, ccmAddr );
358    
359            cl.setExecutable( CCM );
360            cl.createArg().setValue( RECONFIGURE );
361    
362            cl.createArg().setValue( "-recurse" );
363    
364            if ( projectSpec != null )
365            {
366                cl.createArg().setValue( "-p" );
367                cl.createArg().setValue( projectSpec );
368            }
369    
370            return cl;
371    
372        }
373    
374        /**
375         * Create commandline to reconfigure properties of a project.
376         *
377         * @param projectSpec
378         * @param ccmAddr
379         * @return
380         * @throws ScmException
381         */
382        public static Commandline reconfigureProperties( String projectSpec, String ccmAddr )
383            throws ScmException
384        {
385            Commandline cl = new Commandline();
386    
387            configureEnvironment( cl, ccmAddr );
388    
389            cl.setExecutable( CCM );
390            cl.createArg().setValue( RECONFIGURE_PROPERTIES );
391    
392            cl.createArg().setValue( "-refresh" );
393            cl.createArg().setValue( projectSpec );
394    
395            return cl;
396    
397        }
398    
399        /**
400         * Create command line to reconcile a project with uwa option.
401         *
402         * @param projectSpec
403         * @param ccmAddr
404         * @return
405         * @throws ScmException
406         */
407        public static Commandline reconcileUwa( String projectSpec, String ccmAddr )
408            throws ScmException
409        {
410            Commandline cl = new Commandline();
411    
412            configureEnvironment( cl, ccmAddr );
413    
414            cl.setExecutable( CCM );
415            cl.createArg().setValue( RECONCILE );
416    
417            cl.createArg().setValue( "-r" );
418            cl.createArg().setValue( "-uwa" ); // Update wa from database
419    
420            if ( projectSpec != null )
421            {
422                cl.createArg().setValue( "-p" );
423                cl.createArg().setValue( projectSpec );
424            }
425    
426            return cl;
427    
428        }
429    
430        /**
431         * Create command line to reconcile a project with udb option.
432         *
433         * @param projectSpec
434         * @param ccmAddr
435         * @return
436         * @throws ScmException
437         */
438        public static Commandline reconcileUdb( String projectSpec, String ccmAddr )
439            throws ScmException
440        {
441            Commandline cl = new Commandline();
442    
443            configureEnvironment( cl, ccmAddr );
444    
445            cl.setExecutable( CCM );
446            cl.createArg().setValue( RECONCILE );
447    
448            cl.createArg().setValue( "-r" );
449            cl.createArg().setValue( "-udb" ); // Update database from wa
450    
451            if ( projectSpec != null )
452            {
453                cl.createArg().setValue( "-p" );
454                cl.createArg().setValue( projectSpec );
455            }
456    
457            return cl;
458    
459        }
460    
461        /**
462         * Create command line to perform a dir on the directory.
463         *
464         * @param directory
465         * @param format    Output format.
466         * @param ccmAddr
467         * @return
468         * @throws ScmException
469         */
470        public static Commandline dir( File directory, String format, String ccmAddr )
471            throws ScmException
472        {
473            Commandline cl = new Commandline();
474    
475            configureEnvironment( cl, ccmAddr );
476    
477            try
478            {
479                cl.setWorkingDirectory( directory.getCanonicalPath() );
480            }
481            catch ( IOException e )
482            {
483                throw new ScmException( "Invalid directory", e );
484            }
485    
486            cl.setExecutable( CCM );
487            cl.createArg().setValue( DIR );
488            cl.createArg().setValue( "-m" );
489    
490            // Set up the output format
491            if ( format != null && !format.equals( "" ) )
492            {
493                cl.createArg().setValue( "-f" );
494                cl.createArg().setValue( format );
495            }
496    
497            return cl;
498    
499        }
500    
501        /**
502         * Create commandline to checkout a fileset.
503         *
504         * @param files    fileset.
505         * @param ccmAddr
506         * @return the command line.
507         * @throws ScmException
508         */
509        public static Commandline checkoutFiles( List<File> files, String ccmAddr )
510            throws ScmException
511        {
512            Commandline cl = new Commandline();
513    
514            configureEnvironment( cl, ccmAddr );
515    
516            cl.setExecutable( CCM );
517            cl.createArg().setValue( CO );
518    
519            for ( File f : files )
520            {
521                try
522                {
523                    cl.createArg().setValue( f.getCanonicalPath() );
524                }
525                catch ( IOException e )
526                {
527                    throw new ScmException( "Invalid file path " + f.toString(), e );
528                }
529            }
530    
531            return cl;
532        }
533    
534        /**
535         * Create commandline to checkout a project
536         *
537         * @param directory    target WA, or null if using default directory
538         * @param projectSpec
539         * @param version      new version of the project, or null if using default Synergy
540         *                     mecanism
541         * @param ccmAddr
542         * @return
543         * @throws ScmException
544         */
545        public static Commandline checkoutProject( File directory, String projectSpec, ScmVersion version, String purpose,
546                                                   String release, String ccmAddr )
547            throws ScmException
548        {
549            Commandline cl = new Commandline();
550    
551            configureEnvironment( cl, ccmAddr );
552    
553            cl.setExecutable( CCM );
554            cl.createArg().setValue( CO );
555            cl.createArg().setValue( "-subprojects" ); // Checkout sub-projects
556            cl.createArg().setValue( "-rel" ); // Relative
557    
558            if ( version != null && StringUtils.isNotEmpty( version.getName() ) )
559            {
560                cl.createArg().setValue( "-t" ); // Version
561                cl.createArg().setValue( version.getName() );
562            }
563    
564            if ( purpose != null && !purpose.equals( "" ) )
565            {
566                cl.createArg().setValue( "-purpose" );
567                cl.createArg().setValue( purpose );
568            }
569    
570            if ( release != null && !release.equals( "" ) )
571            {
572                cl.createArg().setValue( "-release" );
573                cl.createArg().setValue( release );
574            }
575    
576            if ( directory != null )
577            {
578                cl.createArg().setValue( "-path" );
579                try
580                {
581                    cl.createArg().setValue( directory.getCanonicalPath() );
582                }
583                catch ( IOException e )
584                {
585                    throw new ScmException( "Invalid directory", e );
586                }
587            }
588            cl.createArg().setValue( "-p" );
589            cl.createArg().setValue( projectSpec );
590    
591            return cl;
592        }
593    
594        /**
595         * Create commandline to checkin a project
596         *
597         * @param projectSpec
598         * @param comment
599         * @param ccmAddr
600         * @return
601         * @throws ScmException
602         */
603        public static Commandline checkinProject( String projectSpec, String comment, String ccmAddr )
604            throws ScmException
605        {
606            Commandline cl = new Commandline();
607    
608            configureEnvironment( cl, ccmAddr );
609    
610            cl.setExecutable( CCM );
611            cl.createArg().setValue( CI );
612            if ( comment != null && !comment.equals( "" ) )
613            {
614                cl.createArg().setValue( "-c" );
615                cl.createArg().setValue( comment );
616            }
617            cl.createArg().setValue( "-p" );
618            cl.createArg().setValue( projectSpec );
619    
620            return cl;
621        }
622    
623        /**
624         * Create commandline to checkin a fileset
625         *
626         * @param files    fileset.
627         * @param comment
628         * @param ccmAddr
629         * @return
630         * @throws ScmException
631         */
632        public static Commandline checkinFiles( List<File> files, String comment, String ccmAddr )
633            throws ScmException
634        {
635            Commandline cl = new Commandline();
636    
637            configureEnvironment( cl, ccmAddr );
638    
639            cl.setExecutable( CCM );
640            cl.createArg().setValue( CI );
641            if ( comment != null && !comment.equals( "" ) )
642            {
643                cl.createArg().setValue( "-c" );
644                cl.createArg().setValue( comment );
645            }
646    
647            if ( files.size() > 0 )
648            {
649                for ( File f : files )
650                {
651                    try
652                    {
653                        cl.createArg().setValue( f.getCanonicalPath() );
654                    }
655                    catch ( IOException e )
656                    {
657                        throw new ScmException( "Invalid file path " + f.toString(), e );
658                    }
659                }
660            }
661            return cl;
662        }
663    
664        /**
665         * Create commandline to synchronize a project
666         *
667         * @param projectSpec
668         * @param ccmAddr
669         * @return
670         * @throws ScmException
671         */
672        public static Commandline synchronize( String projectSpec, String ccmAddr )
673            throws ScmException
674        {
675            Commandline cl = new Commandline();
676    
677            configureEnvironment( cl, ccmAddr );
678    
679            cl.setExecutable( CCM );
680            cl.createArg().setValue( SYNC );
681            cl.createArg().setValue( "-r" ); // Recursive
682            cl.createArg().setValue( "-p" );
683            cl.createArg().setValue( projectSpec );
684    
685            return cl;
686        }
687    
688        /**
689         * Create commandline to get workarea informations for a given project.
690         *
691         * @param projectSpec
692         * @param ccmAddr
693         * @return
694         * @throws ScmException
695         */
696        public static Commandline showWorkArea( String projectSpec, String ccmAddr )
697            throws ScmException
698        {
699            Commandline cl = new Commandline();
700    
701            configureEnvironment( cl, ccmAddr );
702    
703            cl.setExecutable( CCM );
704            cl.createArg().setValue( WA );
705            cl.createArg().setValue( "-show" );
706            cl.createArg().setValue( projectSpec );
707    
708            return cl;
709        }
710    
711        /**
712         * Create commandline to stop a Synergy session
713         *
714         * @param ccmAddr
715         * @return
716         * @throws ScmException
717         */
718        public static Commandline stop( String ccmAddr )
719            throws ScmException
720        {
721            Commandline cl = new Commandline();
722    
723            configureEnvironment( cl, ccmAddr );
724    
725            cl.setExecutable( CCM );
726            cl.createArg().setValue( STOP );
727    
728            return cl;
729        }
730    
731        /**
732         * Configure a commandline to use environment variables ($PATH)
733         *
734         * @param cl
735         * @param ccmAddr
736         * @throws ScmException
737         */
738        private static void configureEnvironment( Commandline cl, String ccmAddr )
739            throws ScmException
740        {
741            // We need PATH to be set for using CCM
742            try
743            {
744                Properties envVars = CommandLineUtils.getSystemEnvVars();
745    
746                for ( @SuppressWarnings( "rawtypes" )
747                Iterator i = envVars.keySet().iterator(); i.hasNext(); )
748                {
749                    String key = (String) i.next();
750    
751                    if ( !key.equalsIgnoreCase( "CCM_ADDR" ) )
752                    {
753    
754                        cl.addEnvironment( key, envVars.getProperty( key ) );
755    
756                    }
757                }
758            }
759            catch ( Exception e1 )
760            {
761                throw new ScmException( "Fail to add PATH environment variable.", e1 );
762    
763            }
764            cl.addEnvironment( "CCM_ADDR", ccmAddr );
765    
766        }
767    
768        /**
769         * Create commandline to start a Synergy session
770         *
771         * @param username
772         * @param password
773         * @param role
774         * @return
775         * @throws ScmException
776         */
777        public static Commandline start( String username, String password, SynergyRole role )
778            throws ScmException
779        {
780            Commandline cl = new Commandline();
781    
782            cl.setExecutable( CCM );
783            cl.createArg().setValue( START );
784            cl.createArg().setValue( "-nogui" );
785            cl.createArg().setValue( "-m" ); // Multissesion
786            cl.createArg().setValue( "-q" ); // Quiet (return only CCM_ADDR)
787            cl.createArg().setValue( "-n" );
788            cl.createArg().setValue( username );
789            cl.createArg().setValue( "-pw" );
790            cl.createArg().setValue( password );
791            if ( role != null )
792            {
793                cl.createArg().setValue( "-r" );
794                cl.createArg().setValue( role.toString() );
795            }
796    
797            return cl;
798        }
799    
800        /**
801         * Create commandline to start a  remote Synergy session
802         *
803         * @param username
804         * @param password
805         * @param role
806         * @return
807         * @throws ScmException
808         */
809        public static Commandline startRemote( String username, String password, SynergyRole role )
810            throws ScmException
811        {
812            Commandline cl = new Commandline();
813    
814            cl.setExecutable( CCM );
815            cl.createArg().setValue( START );
816            cl.createArg().setValue( "-nogui" );
817            cl.createArg().setValue( "-m" ); // Multissesion
818            cl.createArg().setValue( "-q" ); // Quiet (return only CCM_ADDR)
819            cl.createArg().setValue( "-rc" ); //Remote client
820            cl.createArg().setValue( "-n" );
821            cl.createArg().setValue( username );
822            cl.createArg().setValue( "-pw" );
823            cl.createArg().setValue( password );
824            if ( role != null )
825            {
826                cl.createArg().setValue( "-r" );
827                cl.createArg().setValue( role.toString() );
828            }
829    
830            return cl;
831        }
832            
833        /**
834         * Create commandline to get Synergy database delimiter
835         *
836         * @return
837         * @throws ScmException
838         */
839        public static Commandline delimiter( String ccmAddr )
840            throws ScmException
841        {
842            Commandline cl = new Commandline();
843    
844            configureEnvironment( cl, ccmAddr );
845    
846            cl.setExecutable( CCM );
847            cl.createArg().setValue( DELIMITER );
848    
849            return cl;
850        }
851        
852        /**
853         * Create commandline to get current (i.e. default) task
854         * 
855         * @param ccmAddr current Synergy session ID
856         * @return 
857         * @throws ScmException
858         */
859        public static Commandline showDefaultTask( String ccmAddr ) 
860            throws ScmException
861        {
862            Commandline cl = new Commandline();
863    
864            configureEnvironment( cl, ccmAddr );
865            cl.setExecutable( CCM );
866            cl.createArg().setValue( TASK );
867            cl.createArg().setValue( "-default" );
868            
869            return cl;
870        }
871        
872        /**
873         * Create commandline to set current (i.e. default) task
874         * 
875         * @param task        the number of the task to set as current task
876         * @param ccmAddr current Synergy session ID
877         * @return 
878         * @throws ScmException
879         */
880        public static Commandline setDefaultTask( int task, String ccmAddr ) 
881            throws ScmException
882        {
883            Commandline cl = new Commandline();
884    
885            configureEnvironment( cl, ccmAddr );
886            cl.setExecutable( CCM );
887            cl.createArg().setValue( TASK );
888            cl.createArg().setValue( "-default" );
889            cl.createArg().setValue( String.valueOf( task ) );
890            return cl;
891        }
892    }