File copy/cut/paste implemented
[pithos] / web_client / src / gr / grnet / pithos / web / client / GSS.java
1 /*
2  * Copyright 2011 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35 package gr.grnet.pithos.web.client;
36
37 import com.google.gwt.core.client.Scheduler;
38 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
39 import com.google.gwt.view.client.SelectionChangeEvent;
40 import com.google.gwt.view.client.SingleSelectionModel;
41 import gr.grnet.pithos.web.client.commands.GetUserCommand;
42 import gr.grnet.pithos.web.client.foldertree.AccountResource;
43 import gr.grnet.pithos.web.client.foldertree.File;
44 import gr.grnet.pithos.web.client.foldertree.Folder;
45 import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
46 import gr.grnet.pithos.web.client.foldertree.FolderTreeViewModel;
47 import gr.grnet.pithos.web.client.rest.GetRequest;
48 import gr.grnet.pithos.web.client.rest.RestException;
49 import gr.grnet.pithos.web.client.rest.resource.FileResource;
50 import gr.grnet.pithos.web.client.rest.resource.OtherUserResource;
51 import gr.grnet.pithos.web.client.rest.resource.RestResource;
52 import gr.grnet.pithos.web.client.rest.resource.RestResourceWrapper;
53 import gr.grnet.pithos.web.client.rest.resource.SharedResource;
54 import gr.grnet.pithos.web.client.rest.resource.TrashResource;
55 import gr.grnet.pithos.web.client.rest.resource.UserResource;
56
57 import java.util.ArrayList;
58 import java.util.Arrays;
59 import java.util.Date;
60 import java.util.HashMap;
61 import java.util.Iterator;
62 import java.util.List;
63
64 import com.google.gwt.core.client.EntryPoint;
65 import com.google.gwt.core.client.GWT;
66 import com.google.gwt.event.logical.shared.ResizeEvent;
67 import com.google.gwt.event.logical.shared.ResizeHandler;
68 import com.google.gwt.event.logical.shared.SelectionEvent;
69 import com.google.gwt.event.logical.shared.SelectionHandler;
70 import com.google.gwt.http.client.URL;
71 import com.google.gwt.i18n.client.DateTimeFormat;
72 import com.google.gwt.resources.client.ClientBundle;
73 import com.google.gwt.resources.client.ImageResource;
74 import com.google.gwt.user.client.Cookies;
75 import com.google.gwt.user.client.Event;
76 import com.google.gwt.user.client.History;
77 import com.google.gwt.user.client.Window;
78 import com.google.gwt.user.client.ui.AbstractImagePrototype;
79 import com.google.gwt.user.client.ui.DecoratedTabPanel;
80 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
81 import com.google.gwt.user.client.ui.HorizontalSplitPanel;
82 import com.google.gwt.user.client.ui.RootPanel;
83 import com.google.gwt.user.client.ui.TabPanel;
84 import com.google.gwt.user.client.ui.VerticalPanel;
85 import java.util.Set;
86
87 /**
88  * Entry point classes define <code>onModuleLoad()</code>.
89  */
90 public class GSS implements EntryPoint, ResizeHandler {
91
92         /**
93          * A constant that denotes the completion of an IncrementalCommand.
94          */
95         public static final boolean DONE = false;
96
97         public static final int VISIBLE_FILE_COUNT = 25;
98
99         /**
100          * Instantiate an application-level image bundle. This object will provide
101          * programmatic access to all the images needed by widgets.
102          */
103         private static Images images = (Images) GWT.create(Images.class);
104
105     public String getUsername() {
106         return username;
107     }
108
109     public void setAccount(AccountResource acct) {
110         account = acct;
111     }
112
113     public AccountResource getAccount() {
114         return account;
115     }
116
117     public void updateFolder(Folder f) {
118         folderTreeView.updateFolder(f);
119     }
120
121     /**
122          * An aggregate image bundle that pulls together all the images for this
123          * application into a single bundle.
124          */
125         public interface Images extends ClientBundle, TopPanel.Images, StatusPanel.Images, FileMenu.Images, EditMenu.Images, SettingsMenu.Images, FilePropertiesDialog.Images, MessagePanel.Images, FileList.Images, Search.Images, CellTreeView.Images {
126
127                 @Source("gr/grnet/pithos/resources/document.png")
128                 ImageResource folders();
129
130                 @Source("gr/grnet/pithos/resources/edit_group_22.png")
131                 ImageResource groups();
132
133                 @Source("gr/grnet/pithos/resources/search.png")
134                 ImageResource search();
135         }
136
137         /**
138          * The single GSS instance.
139          */
140         private static GSS singleton;
141
142         /**
143          * Gets the singleton GSS instance.
144          *
145          * @return the GSS object
146          */
147         public static GSS get() {
148                 if (GSS.singleton == null)
149                         GSS.singleton = new GSS();
150                 return GSS.singleton;
151         }
152
153         /**
154          * The Application Clipboard implementation;
155          */
156         private Clipboard clipboard = new Clipboard();
157
158         private UserResource currentUserResource;
159
160         /**
161          * The top panel that contains the menu bar.
162          */
163         private TopPanel topPanel;
164
165         /**
166          * The panel that contains the various system messages.
167          */
168         private MessagePanel messagePanel = new MessagePanel(GSS.images);
169
170         /**
171          * The bottom panel that contains the status bar.
172          */
173         private StatusPanel statusPanel = null;
174
175         /**
176          * The top right panel that displays the logged in user details
177          */
178         private UserDetailsPanel userDetailsPanel = new UserDetailsPanel();
179
180         /**
181          * The file list widget.
182          */
183         private FileList fileList;
184
185         /**
186          * The tab panel that occupies the right side of the screen.
187          */
188         private TabPanel inner = new DecoratedTabPanel(){
189                 
190 //              public void onBrowserEvent(com.google.gwt.user.client.Event event) {
191 //                      if (DOM.eventGetType(event) == Event.ONCONTEXTMENU){
192 //                              if(isFileListShowing()){
193 //                                      getFileList().showContextMenu(event);
194 //                              }
195 //                      }
196 //              };
197         };
198
199
200         /**
201          * The split panel that will contain the left and right panels.
202          */
203         private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
204
205         /**
206          * The widget that displays the tree of folders.
207          */
208         
209         private CellTreeView treeView = null;
210         /**
211          * The currently selected item in the application, for use by the Edit menu
212          * commands. Potential types are Folder, File, User and Group.
213          */
214         private Object currentSelection;
215
216
217         /**
218          * The WebDAV password of the current user
219          */
220         private String webDAVPassword;
221
222         public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
223
224     private String username = null;
225
226     /**
227      * The authentication token of the current user.
228      */
229     private String token;
230
231     private SingleSelectionModel<Folder> folderTreeSelectionModel;
232     private FolderTreeViewModel folderTreeViewModel;
233     private FolderTreeView folderTreeView;
234
235     private AccountResource account;
236
237         @Override
238         public void onModuleLoad() {
239                 // Initialize the singleton before calling the constructors of the
240                 // various widgets that might call GSS.get().
241                 singleton = this;
242                 if (parseUserCredentials())
243             initialize();
244         }
245
246     private void initialize() {
247         topPanel = new TopPanel(GSS.images);
248         topPanel.setWidth("100%");
249
250         messagePanel.setWidth("100%");
251         messagePanel.setVisible(false);
252
253
254         // Inner contains the various lists.
255         inner.sinkEvents(Event.ONCONTEXTMENU);
256         inner.setAnimationEnabled(true);
257         inner.getTabBar().addStyleName("pithos-MainTabBar");
258         inner.getDeckPanel().addStyleName("pithos-MainTabPanelBottom");
259
260         inner.setWidth("100%");
261
262         inner.addSelectionHandler(new SelectionHandler<Integer>() {
263
264             @Override
265             public void onSelection(SelectionEvent<Integer> event) {
266                 int tabIndex = event.getSelectedItem();
267                 switch (tabIndex) {
268                     case 0:
269                         fileList.updateCurrentlyShowingStats();
270                         break;
271                 }
272             }
273         });
274
275         folderTreeSelectionModel = new SingleSelectionModel<Folder>();
276         folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
277             @Override
278             public void onSelectionChange(SelectionChangeEvent event) {
279                 Folder f = folderTreeSelectionModel.getSelectedObject();
280                 updateFolder(f);
281             }
282         });
283
284         folderTreeViewModel = new FolderTreeViewModel(folderTreeSelectionModel);
285         folderTreeView = new FolderTreeView(folderTreeViewModel);
286
287         fileList = new FileList(images, folderTreeView);
288         inner.add(fileList, createHeaderHTML(AbstractImagePrototype.create(images.folders()), "Files"), true);
289
290         // Add the left and right panels to the split panel.
291         splitPanel.setLeftWidget(folderTreeView);
292         splitPanel.setRightWidget(inner);
293         splitPanel.setSplitPosition("25%");
294         splitPanel.setSize("100%", "100%");
295         splitPanel.addStyleName("pithos-splitPanel");
296
297         // Create a dock panel that will contain the menu bar at the top,
298         // the shortcuts to the left, the status bar at the bottom and the
299         // right panel taking the rest.
300         VerticalPanel outer = new VerticalPanel();
301         outer.add(topPanel);
302         outer.add(messagePanel);
303         outer.add(splitPanel);
304         statusPanel = new StatusPanel(GSS.images);
305         outer.add(statusPanel);
306         outer.setWidth("100%");
307         outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
308
309         outer.setSpacing(4);
310
311         // Hook the window resize event, so that we can adjust the UI.
312         Window.addResizeHandler(this);
313         // Clear out the window's built-in margin, because we want to take
314         // advantage of the entire client area.
315         Window.setMargin("0px");
316         // Finally, add the outer panel to the RootPanel, so that it will be
317         // displayed.
318         RootPanel.get().add(outer);
319         // Call the window resized handler to get the initial sizes setup. Doing
320         // this in a deferred command causes it to occur after all widgets'
321         // sizes have been computed by the browser.
322         Scheduler.get().scheduleDeferred(new ScheduledCommand() {
323
324             @Override
325             public void execute() {
326                 onWindowResized(Window.getClientHeight());
327             }
328         });
329
330         Scheduler.get().scheduleDeferred(new ScheduledCommand() {
331             @Override
332             public void execute() {
333                 fetchAccount();
334             }
335         });
336     }
337
338     public void showFiles(Folder f) {
339         inner.selectTab(0);
340         Set<File> files = f.getFiles();
341         Iterator<File> iter = files.iterator();
342         fetchFile(iter, files);
343     }
344
345     private void fetchFile(final Iterator<File> iter, final Set<File> files) {
346         if (iter.hasNext()) {
347             File file = iter.next();
348             String path = getApiPath() + username + "/" + file.getContainer() + "/" + file.getPath() + "?format=json";
349             GetRequest<File> getFile = new GetRequest<File>(File.class, path, file) {
350                 @Override
351                 public void onSuccess(File result) {
352                     fetchFile(iter, files);
353                 }
354
355                 @Override
356                 public void onError(Throwable t) {
357                     GWT.log("Error getting file", t);
358                     if (t instanceof RestException)
359                         GSS.get().displayError("Error getting file: " + ((RestException) t).getHttpStatusText());
360                     else
361                         GSS.get().displayError("System error fetching file: " + t.getMessage());
362                 }
363             };
364             getFile.setHeader("X-Auth-Token", "0000");
365             Scheduler.get().scheduleDeferred(getFile);
366         }
367         else
368             fileList.setFiles(new ArrayList<File>(files));
369     }
370
371     /**
372          * Parse and store the user credentials to the appropriate fields.
373          */
374         private boolean parseUserCredentials() {
375                 Configuration conf = (Configuration) GWT.create(Configuration.class);
376                 String cookie = conf.authCookie();
377                 String auth = Cookies.getCookie(cookie);
378                 if (auth == null) {
379                         authenticateUser();
380             return false;
381         }
382         else {
383             String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
384             if (authSplit.length != 2) {
385                 authenticateUser();
386                 return false;
387             }
388             else {
389                 username = authSplit[0];
390                 token = authSplit[1];
391                 return true;
392             }
393         }
394         }
395
396     /**
397          * Redirect the user to the login page for authentication.
398          */
399         protected void authenticateUser() {
400                 Configuration conf = (Configuration) GWT.create(Configuration.class);
401
402 //        Window.Location.assign(GWT.getModuleBaseURL() + conf.loginUrl() + "?next=" + Window.Location.getHref());
403         Cookies.setCookie(conf.authCookie(), "test" + conf.cookieSeparator() + "0000");
404         Window.Location.assign(GWT.getModuleBaseURL() + "GSS.html");
405         }
406
407     private void fetchAccount() {
408         String path = getApiPath() + username + "?format=json";
409
410         GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, path) {
411             @Override
412             public void onSuccess(AccountResource result) {
413                 account = result;
414                 statusPanel.displayStats(account);
415                 folderTreeViewModel.initialize(account);
416                 inner.selectTab(0);
417             }
418
419             @Override
420             public void onError(Throwable t) {
421                 GWT.log("Error getting account", t);
422                 if (t instanceof RestException)
423                     GSS.get().displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
424                 else
425                     GSS.get().displayError("System error fetching user data: " + t.getMessage());
426             }
427         };
428         getAccount.setHeader("X-Auth-Token", token);
429         Scheduler.get().scheduleDeferred(getAccount);
430     }
431
432         /**
433          * Clear the cookie and redirect the user to the logout page.
434          */
435         void logout() {
436                 Configuration conf = (Configuration) GWT.create(Configuration.class);
437                 String cookie = conf.authCookie();
438                 String domain = Window.Location.getHostName();
439                 String path = Window.Location.getPath();
440                 Cookies.setCookie(cookie, "", null, domain, path, false);
441         String baseUrl = GWT.getModuleBaseURL();
442         String homeUrl = baseUrl.substring(0, baseUrl.indexOf(path));
443                 Window.Location.assign(homeUrl + conf.logoutUrl());
444         }
445
446         /**
447          * Creates an HTML fragment that places an image & caption together, for use
448          * in a group header.
449          *
450          * @param imageProto an image prototype for an image
451          * @param caption the group caption
452          * @return the header HTML fragment
453          */
454         private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
455                 String captionHTML = "<table class='caption' cellpadding='0' " 
456                 + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML() 
457                 + "</td><td id =" + caption +" class='rcaption'><b style='white-space:nowrap'>&nbsp;" 
458                 + caption + "</b></td></tr></table>";
459                 return captionHTML;
460         }
461
462         private void onWindowResized(int height) {
463                 // Adjust the split panel to take up the available room in the window.
464                 int newHeight = height - splitPanel.getAbsoluteTop() - 44;
465                 if (newHeight < 1)
466                         newHeight = 1;
467                 splitPanel.setHeight("" + newHeight);
468                 inner.setHeight("" + newHeight);
469         }
470
471         @Override
472         public void onResize(ResizeEvent event) {
473                 int height = event.getHeight();
474                 onWindowResized(height);
475         }
476
477         public boolean isFileListShowing() {
478                 int tab = inner.getTabBar().getSelectedTab();
479                 if (tab == 0)
480                         return true;
481                 return false;
482         }
483
484         public boolean isSearchResultsShowing() {
485                 int tab = inner.getTabBar().getSelectedTab();
486                 if (tab == 2)
487                         return true;
488                 return false;
489         }
490
491         /**
492          * Make the file list visible.
493          *
494          * @param update
495          */
496         public void showFileList(boolean update) {
497                 if(update){
498                         getTreeView().refreshCurrentNode(true);
499                 }
500                 else{
501                         RestResource currentFolder = getTreeView().getSelection();
502                         if(currentFolder!=null){
503                                 showFileList(currentFolder);
504                 }
505                 }
506
507         }
508         
509         public void showFileList(RestResource r) {
510                 showFileList(r,true);
511         }
512         
513         public void showFileList(RestResource r, boolean clearSelection) {
514                 RestResource currentFolder = r;
515                 if(currentFolder!=null){
516                         List<FileResource> files = null;
517                         if (currentFolder instanceof RestResourceWrapper) {
518                                 RestResourceWrapper folder = (RestResourceWrapper) currentFolder;
519                                 files = folder.getResource().getFiles();
520                         }
521                 }
522                 inner.selectTab(0);
523         }
524
525         /**
526          * Display the 'loading' indicator.
527          */
528         public void showLoadingIndicator(String message, String path) {
529                 if(path!=null){
530                         String[] split = path.split("/");
531                         message = message +" "+URL.decode(split[split.length-1]);
532                 }
533                 topPanel.getLoading().show(message);
534         }
535
536         /**
537          * Hide the 'loading' indicator.
538          */
539         public void hideLoadingIndicator() {
540                 topPanel.getLoading().hide();
541         }
542
543         /**
544          * A native JavaScript method to reach out to the browser's window and
545          * invoke its resizeTo() method.
546          *
547          * @param x the new width
548          * @param y the new height
549          */
550         public static native void resizeTo(int x, int y) /*-{
551                 $wnd.resizeTo(x,y);
552         }-*/;
553
554         /**
555          * A helper method that returns true if the user's list is currently visible
556          * and false if it is hidden.
557          *
558          * @return true if the user list is visible
559          */
560         public boolean isUserListVisible() {
561                 return inner.getTabBar().getSelectedTab() == 1;
562         }
563
564         /**
565          * Display an error message.
566          *
567          * @param msg the message to display
568          */
569         public void displayError(String msg) {
570                 messagePanel.displayError(msg);
571         }
572
573         /**
574          * Display a warning message.
575          *
576          * @param msg the message to display
577          */
578         public void displayWarning(String msg) {
579                 messagePanel.displayWarning(msg);
580         }
581
582         /**
583          * Display an informational message.
584          *
585          * @param msg the message to display
586          */
587         public void displayInformation(String msg) {
588                 messagePanel.displayInformation(msg);
589         }
590
591         /**
592          * Retrieve the folders.
593          *
594          * @return the folders
595          
596         public Folders getFolders() {
597                 return folders;
598         }*/
599
600         /**
601          * Retrieve the currentSelection.
602          *
603          * @return the currentSelection
604          */
605         public Object getCurrentSelection() {
606                 return currentSelection;
607         }
608
609         /**
610          * Modify the currentSelection.
611          *
612          * @param newCurrentSelection the currentSelection to set
613          */
614         public void setCurrentSelection(Object newCurrentSelection) {
615                 currentSelection = newCurrentSelection;
616         }
617
618         /**
619          * Retrieve the fileList.
620          *
621          * @return the fileList
622          */
623         public FileList getFileList() {
624                 return fileList;
625         }
626
627         /**
628          * Retrieve the topPanel.
629          *
630          * @return the topPanel
631          */
632         TopPanel getTopPanel() {
633                 return topPanel;
634         }
635
636         /**
637          * Retrieve the clipboard.
638          *
639          * @return the clipboard
640          */
641         public Clipboard getClipboard() {
642                 return clipboard;
643         }
644
645         public StatusPanel getStatusPanel() {
646                 return statusPanel;
647         }
648
649         /**
650          * Retrieve the userDetailsPanel.
651          *
652          * @return the userDetailsPanel
653          */
654         public UserDetailsPanel getUserDetailsPanel() {
655                 return userDetailsPanel;
656         }
657
658         
659
660         public String getToken() {
661                 return token;
662         }
663
664         public String getWebDAVPassword() {
665                 return webDAVPassword;
666         }
667
668         /**
669          * Retrieve the currentUserResource.
670          *
671          * @return the currentUserResource
672          */
673         public UserResource getCurrentUserResource() {
674                 return currentUserResource;
675         }
676
677         /**
678          * Modify the currentUserResource.
679          *
680          * @param newUser the new currentUserResource
681          */
682         public void setCurrentUserResource(UserResource newUser) {
683                 currentUserResource = newUser;
684         }
685
686         public static native void preventIESelection() /*-{
687                 $doc.body.onselectstart = function () { return false; };
688         }-*/;
689
690         public static native void enableIESelection() /*-{
691                 if ($doc.body.onselectstart != null)
692                 $doc.body.onselectstart = null;
693         }-*/;
694
695         /**
696          * @return the absolute path of the API root URL
697          */
698         public String getApiPath() {
699                 Configuration conf = (Configuration) GWT.create(Configuration.class);
700                 return conf.apiPath();
701         }
702
703         /**
704          * Convert server date to local time according to browser timezone
705          * and format it according to localized pattern.
706          * Time is always formatted to 24hr format.
707          * NB: This assumes that server runs in UTC timezone. Otherwise
708          * we would need to adjust for server time offset as well.
709          *
710          * @param date
711          * @return String
712          */
713         public static String formatLocalDateTime(Date date) {
714                 Date convertedDate = new Date(date.getTime() - date.getTimezoneOffset());
715                 final DateTimeFormat dateFormatter = DateTimeFormat.getShortDateFormat();
716                 final DateTimeFormat timeFormatter = DateTimeFormat.getFormat("HH:mm");
717                 String datePart = dateFormatter.format(convertedDate);
718                 String timePart = timeFormatter.format(convertedDate);
719                 return datePart + " " + timePart;
720         }
721         
722         /**
723          * History support for folder navigation
724          * adds a new browser history entry
725          *
726          * @param key
727          */
728         public void updateHistory(String key){
729 //              Replace any whitespace of the initial string to "+"
730 //              String result = key.replaceAll("\\s","+");
731 //              Add a new browser history entry.
732 //              History.newItem(result);
733                 History.newItem(key);
734         }
735
736         /**
737          * This method examines the token input and add a "/" at the end in case it's omitted.
738          * This happens only in Files/trash/, Files/shared/, Files/others.
739          *
740          * @param tokenInput
741          * @return the formated token with a "/" at the end or the same tokenInput parameter
742          */
743
744         private String handleSpecialFolderNames(String tokenInput){
745                 List<String> pathsToCheck = Arrays.asList("Files/trash", "Files/shared", "Files/others");
746                 if(pathsToCheck.contains(tokenInput))
747                         return tokenInput + "/";
748                 return tokenInput;
749
750         }
751
752         /**
753          * Reject illegal resource names, like '.' or '..' or slashes '/'.
754          */
755         static boolean isValidResourceName(String name) {
756                 if (".".equals(name) || "..".equals(name) || name.contains("/"))
757                         return false;
758                 return true;
759         }
760
761         public void putUserToMap(String _userName, String _userFullName){
762                 userFullNameMap.put(_userName, _userFullName);
763         }
764
765         public String findUserFullName(String _userName){
766                 return userFullNameMap.get(_userName);
767         }
768         public String getUserFullName(String _userName) {
769                 
770         if (GSS.get().findUserFullName(_userName) == null)
771                 //if there is no userFullName found then the map fills with the given _userName,
772                 //so userFullName = _userName
773                 GSS.get().putUserToMap(_userName, _userName);
774         else if(GSS.get().findUserFullName(_userName).indexOf('@') != -1){
775                 //if the userFullName = _userName the GetUserCommand updates the userFullName in the map
776                 GetUserCommand guc = new GetUserCommand(_userName);
777                 guc.execute();
778         }
779         return GSS.get().findUserFullName(_userName);
780         }
781         /**
782          * Retrieve the treeView.
783          *
784          * @return the treeView
785          */
786         public CellTreeView getTreeView() {
787                 return treeView;
788         }
789         
790         public void onResourceUpdate(RestResource resource,boolean clearSelection){
791                 if(resource instanceof RestResourceWrapper || resource instanceof OtherUserResource || resource instanceof TrashResource || resource instanceof SharedResource){
792                         if(getTreeView().getSelection()!=null&&getTreeView().getSelection().getUri().equals(resource.getUri()))
793                                 showFileList(resource,clearSelection);
794                 }
795                 
796         }
797 }