001    /*
002    
003      $Id: UserInterface.java,v 1.19 2003/05/08 18:58:28 ndulgheru Exp $
004    
005    */
006    
007    package sharpster.client.userinterface;
008    
009    import sharpster.client.daemoncommunication.*;
010    import sharpster.client.localplugin.*;
011    import sharpster.common.*;
012    
013    import java.util.LinkedList;
014    
015    /**
016     * Class responsible for user interaction. It is used by the user of the
017     * local client, but none of the modules knows of the class.
018     */
019    
020    public class UserInterface {
021    
022        private DaemonCommunication daemonCommunication;
023        private LocalPluginManager localPluginManager;
024    
025        private LinkedList remArgs;
026        private ResponseCollection response;
027    
028        /**
029         * Constructs a user interface object
030         */
031        public UserInterface(DaemonCommunication dc,
032                             LocalPluginManager lpm) {
033            daemonCommunication = dc;
034            localPluginManager = lpm;
035            remArgs = null;
036            response = null;
037        }
038    
039        /**
040         * Functions prints a usage message to user, in case of erroneous input.
041         */
042        private void printUsage() {
043            System.out.println("Usage for sharpster:");
044            System.out.println("share --file <files> --user <users> --rights r|w|d [--part <name> pluginparams]");
045            System.out.println("unshare --file <files> --user <users>");
046            System.out.println("");
047            System.out.println("checkout --file <files> --user <user> [--role <role>]");
048            System.out.println("commit --file <files> --user <user> [--role <role>]");
049            System.out.println("update --file <files> --user <user>");
050            System.out.println("");
051            System.out.println("group --command <command>");
052            System.out.println("");
053            System.out.println("list [--local-shares] [--remote-shares] [--remote-users]");
054            System.out.println("cvs cvs-commands");
055            System.out.println("sync directory");
056        }
057    
058        /**
059         * Utility function to compare two strings without regarding case.
060         */
061        private boolean compareStrings(String lhs,
062                                       String rhs) {
063            return lhs.equalsIgnoreCase(rhs);
064        }
065    
066        /**
067         * Parses user input and and delegates the handling of
068         * each command to the correct private method
069         */
070        public void parseUserInput(String[] argv) {
071            int length = argv.length;
072            remArgs = new LinkedList();
073    
074            /* do we have a first argument? */
075            if (length < 1) {
076                System.out.println("Error : To few arguments");
077                printUsage();
078                return;
079            }
080    
081            /* build linked list (easier to manipulate) of arguments. */
082            for (int i = 1; i<length; i++) {
083                remArgs.add(argv[i]);
084            }
085    
086    
087            if (argv[0].equalsIgnoreCase("share")) {
088                parseShare();
089            } else if(argv[0].equalsIgnoreCase("unshare")) {
090                parseUnshare();
091            } else if (argv[0].equalsIgnoreCase("checkout")) {
092                parseCheckout();
093            } else if (argv[0].equalsIgnoreCase("update")) {
094                parseUpdate();
095            } else if (argv[0].equalsIgnoreCase("commit")) {
096                parseCommit();
097            } else if (argv[0].equalsIgnoreCase("group")) {
098                parseGroup();
099            } else if (argv[0].equalsIgnoreCase("remove")) {
100                parseRemove();
101            } else if (argv[0].equalsIgnoreCase("list")) {
102                parseList();
103            } else if (argv[0].equalsIgnoreCase("cvs")) {
104                parseCVS();
105            } else if (argv[0].equalsIgnoreCase("sync")) {
106                parseSync();
107            } else {
108                System.out.println("Unknown command "+argv[0]);
109                printUsage();
110            }
111            if (null != response) {
112                printResponse();
113            }
114        }
115    
116        /**
117         * Function prints response that comes back from daemon.
118         */
119        private void printResponse() {
120            Response res = null;
121            System.out.println("Responses from the daemon:\n");
122            for (int i=0; i < response.getResponseCount(); i++) {
123                res = response.getResponse(i);
124                if(res != null) {
125                    System.out.println(res.toString());
126                }
127            }
128        }
129    
130        /**
131         * utility function: compare first argument of linked list to string cmp
132         */
133        private boolean cmpFirstArg(String cmp) {
134            boolean retval = false;
135            try {
136                String first = (String) remArgs.getFirst();
137                retval = first.equalsIgnoreCase(cmp);
138            } catch (Exception e) {
139                retval = false;
140            }
141            return retval;
142        }
143    
144        /**
145         * utility function: compare without case first argument
146         * of linked list to string cmp
147         */
148        private boolean cmpFirstArgCase(String cmp) {
149            boolean retval = false;
150            try {
151                String first = (String) remArgs.getFirst();
152                retval = first.equals(cmp);
153            } catch (Exception e) {
154                retval = false;
155            }
156            return retval;
157        }
158    
159        /**
160         * utility function: compare with no case first arg with a prefix
161         */
162        private boolean cmpFirstArgToPrefix(String cmp) {
163            boolean retval = false;
164            try {
165                String first = (String) remArgs.getFirst();
166                retval = first.startsWith(cmp);
167            } catch (Exception e) {
168                retval = false;
169            }
170            return retval;
171        }
172    
173        /**
174         * utility function: removes first argument of linked list.
175         */
176        private void removeFirstArg() {
177            try {
178                remArgs.removeFirst();
179            } catch (Exception e) { }
180        }
181    
182        /**
183         * utility function: checks that first argument of linked list exists.
184         */
185        private boolean firstArgExists() {
186            return (remArgs.size() > 0);
187        }
188    
189        /**
190         * utility function: returns true if next argument is a parameter, that is
191         * it starts with a dash
192         */
193        private boolean firstArgIsParam() {
194            return cmpFirstArgToPrefix("-");
195        }
196    
197    
198        /**
199         * parseParam* returns true if it was there and parsed correctly.
200         * These functions remove their corresponding arguments from the
201         * linked list remArgs.
202         */
203    
204        /**
205         * Fills in FileCollection files, removes its
206         * according parameters from remArgs
207         */
208        private boolean parseParamFile(FileCollection files) {
209            if (!firstArgExists())
210                return false;
211            if (!(cmpFirstArg("--file") ||
212                  cmpFirstArgCase("-f")))
213                return false;
214    
215            /* Eat --file or -f */
216            removeFirstArg();
217    
218            /* a list with arguments after --file that belongs to me */
219            LinkedList myargs = new LinkedList();
220            while (firstArgExists() && !firstArgIsParam()) {
221                myargs.add(remArgs.getFirst());
222                removeFirstArg();
223            }
224    
225            /* If file argument was given, but no files return false */
226            if (myargs.size() < 1)
227                return false;
228    
229            while (myargs.size() > 0) {
230                SharedFile afile = new SharedFile();
231                afile.setFileName((String) myargs.getFirst());
232                /* TODO : set other necessary stuff. */
233                files.addFile(afile);
234                myargs.removeFirst();
235            }
236    
237            return true;
238        }
239    
240        /**
241         * returns true if user exists on commandline and
242         * there exists at least one user
243         */
244        private boolean parseParamUsers(FileCollection files) {
245            if (!firstArgExists())
246                return false;
247    
248            if (!(cmpFirstArg("--user") ||
249                  cmpFirstArgCase("-u")))
250                return false;
251    
252            /* Eat --user or -u */
253            removeFirstArg();
254    
255            /* a list with arguments after --file that belongs to me */
256            LinkedList myargs = new LinkedList();
257            while (firstArgExists() && !firstArgIsParam()) {
258                myargs.add(remArgs.getFirst());
259                removeFirstArg();
260            }
261    
262            /* If user argument was given, but no users return false */
263            if (myargs.size() < 1)
264                return false;
265    
266            for (int i=0; i<files.getFileCount(); i++) {
267                SharedFile afile = (SharedFile) files.getFile(i);
268                if (null == afile)
269                    return false;
270                for (int j=0; j<myargs.size(); j++) {
271                    String user = (String) myargs.get(j);
272                    //              afile.addSharedToUser((String) myargs.get(j));
273                    afile.addSharedToUser(user);
274                    /* TODO : set other necessary stuff. */
275                }
276            }
277            return true;
278        }
279    
280        /**
281         * returns null if false, otherwise the user to check out from
282         */
283        private String parseParamUser() {
284            if (!firstArgExists())
285                return null;
286    
287            if (!(cmpFirstArg("--user") ||
288                  cmpFirstArgCase("-u")))
289                return null;
290    
291            /* Eat --user or -u */
292            removeFirstArg();
293    
294            if (!firstArgExists())
295                return null;
296    
297            String user = null;
298            try {
299                user = new String((String) remArgs.getFirst());
300                removeFirstArg();
301            } catch (Exception e) {
302                user = null;
303            }
304            return user;
305        }
306    
307        /**
308         * Returns true if the parameter "--rights" or "-r" exists
309         * on commandline and it parses correctly.
310         */
311        private boolean parseParamRights(FileCollection files) {
312            if (!firstArgExists())
313                return false;
314    
315            if (!(cmpFirstArg("--rights") ||
316                  cmpFirstArgCase("-r")))
317                return false;
318    
319            /* Eat --rights or -r */
320            removeFirstArg();
321    
322            if (!firstArgExists())
323                return false;
324    
325            String acc = (String) remArgs.getFirst();
326            removeFirstArg();
327    
328            boolean read   = acc.indexOf("r") == -1 ? false : true;
329            boolean write  = acc.indexOf("w") == -1 ? false : true;
330            boolean delete = acc.indexOf("d") == -1 ? false : true;
331    
332            for (int i=0; i<files.getFileCount(); i++) {
333                SharedFile afile = files.getFile(i);
334                if (null == afile)
335                    return false;
336                if (read)
337                    afile.setAccessRead();
338                if (write)
339                    afile.setAccessWrite();
340                if (delete)
341                    afile.setAccessDelete();
342            }
343    
344            return true;
345        }
346    
347        /**
348         * returns true if part exists on commandline and
349         * plugin manager parses the rest ok.
350         */
351        private boolean parseParamPart(FileCollection files) {
352            if(!firstArgExists()) {
353                for(int i=0;i<files.getFileCount();i++) {
354                    SharedFile file = files.getFile(i);
355                    PluginData data = localPluginManager.parseArguments(null);
356                    if(data == null) {
357                        System.out.println("Fatal error: no default plugin loaded");
358                        System.exit(1);
359                    }
360                    file.setPluginData(data);
361                }
362                return true;
363            }
364            if(cmpFirstArg("--part") ||
365                cmpFirstArgCase("-p")) {
366                removeFirstArg();
367    
368                PluginData data = localPluginManager.parseArguments(remArgs);
369                if(data == null) {
370                    System.out.println("Fatal error: unable to parse plug-in arguments");
371                    System.exit(1);
372                }
373    
374                for(int i=0;i<files.getFileCount();i++) {
375                    SharedFile file = files.getFile(i);
376                    file.setPluginData(data);
377                }
378    
379                return true;
380            }
381            return false;
382        }
383    
384        /**
385         * returns true if recursive parameter exists in command
386         */
387        private boolean parseParamRecursive() {
388            if (!firstArgExists())
389                return false;
390            if (cmpFirstArg("--recursive") ||
391                cmpFirstArgCase("-R")) {
392                removeFirstArg();
393                return true;
394            }
395            return false;
396        }
397    
398        /**
399         * parseShare/Unshare/Checkout/...
400         * parses one command, responsible for checking necessary,
401         * optional parameters.
402         */
403    
404        /**
405         * parseShare parses share command for correct and
406         * necessary parameters.
407         */
408        private void parseShare() {
409            FileCollection files = new FileCollection();
410            boolean recursive = false;
411            if (!parseParamFile(files)) {
412                System.out.println("Missing files for share!");
413                printUsage();
414                return;
415            }
416            if (!parseParamUsers(files)) {
417                System.out.println("Missing users for share!");
418                printUsage();
419                return;
420            }
421            recursive = parseParamRecursive();
422            if (!parseParamRights(files)) {
423                System.out.println("Missing rights for share!");
424                printUsage();
425                return;
426            }
427            parseParamPart(files);
428            /* TODO: what to do with recursive boolean parameter??
429               overloaded function in daemoncommunication */
430            response = daemonCommunication.shareFiles(files);
431        }
432    
433        /**
434         * parseUnshare parses unshare command for correct and
435         * necessary parameters.
436         */
437        private void parseUnshare() {
438            FileCollection files = new FileCollection();
439            boolean recursive = false;
440            if (!parseParamFile(files)) {
441                System.out.println("Missing files for unshare!");
442                printUsage();
443                return;
444            }
445            if (!parseParamUsers(files)) {
446                System.out.println("Missing users for unshare!");
447                printUsage();
448                return;
449            }
450            recursive = parseParamRecursive();
451            /* TODO: recursive parameter */
452            response = daemonCommunication.unShareFiles(files);
453        }
454    
455        /**
456         * parseCheckout parses checkout command for correct and
457         * necessary parameters.
458         */
459        private void parseCheckout() {
460            FileCollection files = new FileCollection();
461            boolean recursive = false;
462            if (!parseParamFile(files)) {
463                System.out.println("Missing files for checkout!");
464                printUsage();
465                return;
466            }
467            String user = parseParamUser();
468            if (null == user) {
469                System.out.println("Missing user for checkout!");
470                printUsage();
471                return;
472            }
473    
474            String role = parseParamRole();
475    
476            recursive = parseParamRecursive();
477            /* TODO: recursive parameter, username, workingdirectory */
478            response = daemonCommunication.remoteCheckoutFiles(files, user, role);
479        }
480    
481        /**
482         * parseCheckout parses checkout command for correct and
483         * necessary parameters.
484         */
485        private void parseUpdate() {
486            System.out.println("asdasdasdas");
487    
488            FileCollection files = new FileCollection();
489            boolean recursive = false;
490            if (!parseParamFile(files)) {
491                System.out.println("Missing files for update!");
492                printUsage();
493                return;
494            }
495            String user = parseParamUser();
496            if (null == user) {
497                System.out.println("Missing user for update!");
498                printUsage();
499                return;
500            }
501            recursive = parseParamRecursive();
502            /* TODO: recursive parameter, username, workingdirectory */
503            response = daemonCommunication.remoteUpdateFiles(files, user);
504        }
505    
506        /**
507         * parseCommit parses commit command for correct and
508         * necessary parameters.
509         */
510        private void parseCommit() {
511            FileCollection files = new FileCollection();
512            boolean recursive = false;
513            if (!parseParamFile(files)) {
514                System.out.println("Missing files for commit!");
515                printUsage();
516                return;
517            }
518            String user = parseParamUser();
519            if (null == user) {
520                System.out.println("Missing user for commit!");
521                printUsage();
522                return;
523            }
524    
525            String role = parseParamRole();
526    
527            recursive = parseParamRecursive();
528            /* TODO: recursive parameter, username, workingdirectory */
529            response = daemonCommunication.remoteCommitFiles(files, user, role);
530        }
531    
532    
533        private void parseGroup() {
534          String command = parseParamCommand();
535          if (null == command) {
536            System.out.println("Missing command for group!");
537            printUsage();
538            return;
539          }
540    
541          GroupCommand gc = new GroupCommand();
542    
543          if(command.equalsIgnoreCase("ADD-USER")) {
544    
545            String user = parseParamUser();
546            if (null == user) {
547              System.out.println("Missing username in group command!");
548              printUsage();
549              return;
550            }
551            String group = parseParamGroup();
552            if (null == group) {
553              System.out.println("Missing groupname in group command!");
554              printUsage();
555              return;
556            }
557    
558            gc.command = SubCommand.ADD_USER;
559            gc.user = user;
560            gc.group = group;
561    
562          } else if(command.equalsIgnoreCase("REMOVE-USER")) {
563    
564            String user = parseParamUser();
565            if (null == user) {
566              System.out.println("Missing username in group command!");
567              printUsage();
568              return;
569            }
570            String group = parseParamGroup();
571            if (null == group) {
572              System.out.println("Missing groupname in group command!");
573              printUsage();
574              return;
575            }
576    
577            gc.command = SubCommand.REMOVE_USER;
578            gc.user = user;
579            gc.group = group;
580    
581          } else if(command.equalsIgnoreCase("LIST-GROUPS")) {
582    
583            gc.command = SubCommand.LIST_GROUPS;
584    
585          } else if(command.equalsIgnoreCase("LIST-ALL")) {
586    
587            gc.command = SubCommand.LIST_ALL;
588    
589          } else if(command.equalsIgnoreCase("LIST-USERS-IN-GROUP")) {
590    
591            String group = parseParamGroup();
592            if (null == group) {
593              System.out.println("Missing groupname in group command!");
594              printUsage();
595              return;
596            }
597    
598            gc.command = SubCommand.LIST_USERS_IN_GROUP;
599            gc.group = group;
600    
601          } else if(command.equalsIgnoreCase("ADD-GROUP")) {
602    
603            String group = parseParamGroup();
604            if (null == group) {
605              System.out.println("Missing groupname in group command!");
606              printUsage();
607              return;
608            }
609    
610            gc.command = SubCommand.ADD_GROUP;
611            gc.group = group;
612    
613          } else if(command.equalsIgnoreCase("REMOVE-GROUP")) {
614    
615            String group = parseParamGroup();
616            if (null == group) {
617              System.out.println("Missing groupname in group command!");
618              printUsage();
619              return;
620            }
621    
622            gc.command = SubCommand.REMOVE_GROUP;
623            gc.group = group;
624    
625          } else {
626            System.out.println("Unknown command in group");
627            printUsage();
628            return;
629          }
630    
631          response = daemonCommunication.groupCommand(gc);
632          
633        }
634    
635        /**
636         * returns null if false, otherwise the command to do.
637         */
638        private String parseParamCommand() {
639          if (!firstArgExists())
640            return null;
641    
642          if (! (cmpFirstArg("--command") ||
643                 cmpFirstArgCase("-c")))
644            return null;
645    
646          /* Eat --command or -c */
647          removeFirstArg();
648    
649          if (!firstArgExists())
650            return null;
651    
652          String command = null;
653          try {
654            command = new String( (String) remArgs.getFirst());
655            removeFirstArg();
656          }
657          catch (Exception e) {
658            command = null;
659          }
660          return command;
661    
662        }
663    
664        /**
665         * returns null if false, otherwise the group name.
666         */
667        private String parseParamGroup() {
668          if (!firstArgExists())
669            return null;
670    
671          if (! (cmpFirstArg("--group") ||
672                 cmpFirstArgCase("-g")))
673            return null;
674    
675          /* Eat --group or -g */
676          removeFirstArg();
677    
678          if (!firstArgExists())
679            return null;
680    
681          String group = null;
682          try {
683            group = new String( (String) remArgs.getFirst());
684            removeFirstArg();
685          }
686          catch (Exception e) {
687            group = null;
688          }
689          return group;
690    
691        }
692    
693        /**
694         * returns null if false, otherwise the role to use.
695         */
696        private String parseParamRole() {
697          if (!firstArgExists())
698            return null;
699    
700          if (! (cmpFirstArg("--role") ||
701                 cmpFirstArgCase("-r")))
702            return null;
703    
704          /* Eat --role or -r */
705          removeFirstArg();
706    
707          if (!firstArgExists())
708            return null;
709    
710          String role = null;
711          try {
712            role = new String( (String) remArgs.getFirst());
713            removeFirstArg();
714          }
715          catch (Exception e) {
716            role = null;
717          }
718          return role;
719        }
720    
721        /**
722         * parseRemove parses remove command for correct and
723         * necessary parameters.
724         */
725        private void parseRemove() {
726            FileCollection files = new FileCollection();
727            boolean recursive = false;
728            if (!parseParamFile(files)) {
729                System.out.println("Missing files for commit!");
730                printUsage();
731                return;
732            }
733            String user = parseParamUser();
734            if (null == user) {
735                System.out.println("Missing user for commit!");
736                printUsage();
737                return;
738            }
739            recursive = parseParamRecursive();
740            /* TODO: recursive parameter, username, workingdirectory */
741            response = daemonCommunication.remoteRemoveFiles(files, user);
742        }
743    
744        /**
745         * parseList parses list command for correct and
746         * necessary parameters.
747         */
748        private void parseList() {
749            boolean atLeastOneArg = false;
750            while (firstArgExists()) {
751                atLeastOneArg = true;
752                if (cmpFirstArg("--local-shares")||
753                    cmpFirstArgCase("-ls")) {
754                    removeFirstArg();
755                    response = daemonCommunication.viewFileSharing();
756                    if (null != response) {
757                        printResponse();
758                        response = null;
759                    }
760                } else if (cmpFirstArg("--remote-shares")||
761                           cmpFirstArgCase("-rs")) {
762                    removeFirstArg();
763                    response = daemonCommunication.viewFileAccess();
764                    if (null != response) {
765                        printResponse();
766                        response = null;
767                    }
768                } else if (cmpFirstArg("--remote-users")||
769                           cmpFirstArgCase("-ru")) {
770                    removeFirstArg();
771                    response = daemonCommunication.viewUsers();
772                    if (null != response) {
773                        printResponse();
774                        response = null;
775                    }
776                } else {
777                    System.out.println("Missing or misspelled argument for list argument!");
778                    printUsage();
779                    return;
780                }
781    
782            }
783    
784            if (!atLeastOneArg) {
785                System.out.println("Missing atleast one argument for list!");
786                printUsage();
787            }
788        }
789    
790        /**
791         * parseSync parses sync command for correct and
792         * necessary parameters.
793         */
794        private void parseSync() {
795            response = daemonCommunication.synchronizeCVS();
796        }
797    
798        /**
799         * parseCVS parses cvs command for correct and
800         * necessary parameters.
801         */
802        private void parseCVS() {
803            if (!firstArgExists()) {
804                System.out.println("Missing command-string for cvs command");
805                printUsage();
806                return;
807            }
808            String cmd = new String();
809            while (firstArgExists()) {
810                cmd = cmd + " " + (String) remArgs.getFirst();
811                removeFirstArg();
812            }
813            response = daemonCommunication.localDoCVS(cmd);
814        }
815    
816    }
817    
818    
819    
820    
821    
822    
823    
824    
825