Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / GSS.java @ a6592a15

History | View | Annotate | Download (33.3 kB)

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.http.client.Request;
40
import com.google.gwt.http.client.RequestBuilder;
41
import com.google.gwt.http.client.RequestCallback;
42
import com.google.gwt.http.client.RequestException;
43
import com.google.gwt.http.client.Response;
44
import com.google.gwt.json.client.JSONArray;
45
import com.google.gwt.json.client.JSONObject;
46
import com.google.gwt.json.client.JSONParser;
47
import com.google.gwt.json.client.JSONString;
48
import com.google.gwt.json.client.JSONValue;
49
import com.google.gwt.user.client.Command;
50
import com.google.gwt.view.client.SelectionChangeEvent;
51
import com.google.gwt.view.client.SingleSelectionModel;
52
import gr.grnet.pithos.web.client.commands.GetUserCommand;
53
import gr.grnet.pithos.web.client.foldertree.AccountResource;
54
import gr.grnet.pithos.web.client.foldertree.File;
55
import gr.grnet.pithos.web.client.foldertree.Folder;
56
import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
57
import gr.grnet.pithos.web.client.foldertree.FolderTreeViewModel;
58
import gr.grnet.pithos.web.client.foldertree.Resource;
59
import gr.grnet.pithos.web.client.rest.DeleteRequest;
60
import gr.grnet.pithos.web.client.rest.GetRequest;
61
import gr.grnet.pithos.web.client.rest.PutRequest;
62
import gr.grnet.pithos.web.client.rest.RestException;
63
import gr.grnet.pithos.web.client.rest.resource.FileResource;
64
import gr.grnet.pithos.web.client.rest.resource.OtherUserResource;
65
import gr.grnet.pithos.web.client.rest.resource.RestResource;
66
import gr.grnet.pithos.web.client.rest.resource.RestResourceWrapper;
67
import gr.grnet.pithos.web.client.rest.resource.SharedResource;
68
import gr.grnet.pithos.web.client.rest.resource.TrashResource;
69
import gr.grnet.pithos.web.client.rest.resource.UserResource;
70

    
71
import gr.grnet.pithos.web.client.tagtree.Tag;
72
import gr.grnet.pithos.web.client.tagtree.TagTreeView;
73
import gr.grnet.pithos.web.client.tagtree.TagTreeViewModel;
74
import java.util.ArrayList;
75
import java.util.Arrays;
76
import java.util.Date;
77
import java.util.HashMap;
78
import java.util.Iterator;
79
import java.util.List;
80

    
81
import com.google.gwt.core.client.EntryPoint;
82
import com.google.gwt.core.client.GWT;
83
import com.google.gwt.event.logical.shared.ResizeEvent;
84
import com.google.gwt.event.logical.shared.ResizeHandler;
85
import com.google.gwt.event.logical.shared.SelectionEvent;
86
import com.google.gwt.event.logical.shared.SelectionHandler;
87
import com.google.gwt.http.client.URL;
88
import com.google.gwt.i18n.client.DateTimeFormat;
89
import com.google.gwt.resources.client.ClientBundle;
90
import com.google.gwt.resources.client.ImageResource;
91
import com.google.gwt.user.client.Cookies;
92
import com.google.gwt.user.client.Event;
93
import com.google.gwt.user.client.History;
94
import com.google.gwt.user.client.Window;
95
import com.google.gwt.user.client.ui.AbstractImagePrototype;
96
import com.google.gwt.user.client.ui.DecoratedTabPanel;
97
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
98
import com.google.gwt.user.client.ui.HorizontalSplitPanel;
99
import com.google.gwt.user.client.ui.RootPanel;
100
import com.google.gwt.user.client.ui.TabPanel;
101
import com.google.gwt.user.client.ui.VerticalPanel;
102
import java.util.Set;
103

    
104
/**
105
 * Entry point classes define <code>onModuleLoad()</code>.
106
 */
107
public class GSS implements EntryPoint, ResizeHandler {
108

    
109
        /**
110
         * A constant that denotes the completion of an IncrementalCommand.
111
         */
112
        public static final boolean DONE = false;
113

    
114
        public static final int VISIBLE_FILE_COUNT = 25;
115

    
116
        /**
117
         * Instantiate an application-level image bundle. This object will provide
118
         * programmatic access to all the images needed by widgets.
119
         */
120
        private static Images images = (Images) GWT.create(Images.class);
121

    
122
    public String getUsername() {
123
        return username;
124
    }
125

    
126
    public void setAccount(AccountResource acct) {
127
        account = acct;
128
    }
129

    
130
    public AccountResource getAccount() {
131
        return account;
132
    }
133

    
134
    public void updateFolder(Folder f) {
135
        folderTreeView.updateFolder(f);
136
    }
137

    
138
    /**
139
         * An aggregate image bundle that pulls together all the images for this
140
         * application into a single bundle.
141
         */
142
        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 {
143

    
144
                @Source("gr/grnet/pithos/resources/document.png")
145
                ImageResource folders();
146

    
147
                @Source("gr/grnet/pithos/resources/edit_group_22.png")
148
                ImageResource groups();
149

    
150
                @Source("gr/grnet/pithos/resources/search.png")
151
                ImageResource search();
152
        }
153

    
154
        /**
155
         * The single GSS instance.
156
         */
157
        private static GSS singleton;
158

    
159
        /**
160
         * Gets the singleton GSS instance.
161
         *
162
         * @return the GSS object
163
         */
164
        public static GSS get() {
165
                if (GSS.singleton == null)
166
                        GSS.singleton = new GSS();
167
                return GSS.singleton;
168
        }
169

    
170
        /**
171
         * The Application Clipboard implementation;
172
         */
173
        private Clipboard clipboard = new Clipboard();
174

    
175
        private UserResource currentUserResource;
176

    
177
        /**
178
         * The top panel that contains the menu bar.
179
         */
180
        private TopPanel topPanel;
181

    
182
        /**
183
         * The panel that contains the various system messages.
184
         */
185
        private MessagePanel messagePanel = new MessagePanel(GSS.images);
186

    
187
        /**
188
         * The bottom panel that contains the status bar.
189
         */
190
        private StatusPanel statusPanel = null;
191

    
192
        /**
193
         * The top right panel that displays the logged in user details
194
         */
195
        private UserDetailsPanel userDetailsPanel = new UserDetailsPanel();
196

    
197
        /**
198
         * The file list widget.
199
         */
200
        private FileList fileList;
201

    
202
        /**
203
         * The tab panel that occupies the right side of the screen.
204
         */
205
        private TabPanel inner = new DecoratedTabPanel(){
206
                
207
//                public void onBrowserEvent(com.google.gwt.user.client.Event event) {
208
//                        if (DOM.eventGetType(event) == Event.ONCONTEXTMENU){
209
//                                if(isFileListShowing()){
210
//                                        getFileList().showContextMenu(event);
211
//                                }
212
//                        }
213
//                };
214
        };
215

    
216

    
217
        /**
218
         * The split panel that will contain the left and right panels.
219
         */
220
        private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
221

    
222
        /**
223
         * The widget that displays the tree of folders.
224
         */
225
        
226
        private CellTreeView treeView = null;
227
        /**
228
         * The currently selected item in the application, for use by the Edit menu
229
         * commands. Potential types are Folder, File, User and Group.
230
         */
231
        private Object currentSelection;
232

    
233

    
234
        /**
235
         * The WebDAV password of the current user
236
         */
237
        private String webDAVPassword;
238

    
239
        public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
240

    
241
    private String username = null;
242

    
243
    /**
244
     * The authentication token of the current user.
245
     */
246
    private String token;
247

    
248
    private SingleSelectionModel<Folder> folderTreeSelectionModel;
249
    private FolderTreeViewModel folderTreeViewModel;
250
    private FolderTreeView folderTreeView;
251

    
252
    private SingleSelectionModel<Tag> tagTreeSelectionModel;
253
    private TagTreeViewModel tagTreeViewModel;
254
    private TagTreeView tagTreeView;
255

    
256
    private AccountResource account;
257

    
258
        @Override
259
        public void onModuleLoad() {
260
                // Initialize the singleton before calling the constructors of the
261
                // various widgets that might call GSS.get().
262
                singleton = this;
263
                if (parseUserCredentials())
264
            initialize();
265
        }
266

    
267
    private void initialize() {
268
        topPanel = new TopPanel(GSS.images);
269
        topPanel.setWidth("100%");
270

    
271
        messagePanel.setWidth("100%");
272
        messagePanel.setVisible(false);
273

    
274

    
275
        // Inner contains the various lists.
276
        inner.sinkEvents(Event.ONCONTEXTMENU);
277
        inner.setAnimationEnabled(true);
278
        inner.getTabBar().addStyleName("pithos-MainTabBar");
279
        inner.getDeckPanel().addStyleName("pithos-MainTabPanelBottom");
280

    
281
        inner.setWidth("100%");
282

    
283
        inner.addSelectionHandler(new SelectionHandler<Integer>() {
284

    
285
            @Override
286
            public void onSelection(SelectionEvent<Integer> event) {
287
                int tabIndex = event.getSelectedItem();
288
                switch (tabIndex) {
289
                    case 0:
290
                        fileList.updateCurrentlyShowingStats();
291
                        break;
292
                }
293
            }
294
        });
295

    
296
        folderTreeSelectionModel = new SingleSelectionModel<Folder>();
297
        folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
298
            @Override
299
            public void onSelectionChange(SelectionChangeEvent event) {
300
                Folder f = folderTreeSelectionModel.getSelectedObject();
301
                updateFolder(f);
302
            }
303
        });
304

    
305
        folderTreeViewModel = new FolderTreeViewModel(folderTreeSelectionModel);
306
        folderTreeView = new FolderTreeView(folderTreeViewModel);
307

    
308
        fileList = new FileList(images, folderTreeView);
309
        inner.add(fileList, createHeaderHTML(AbstractImagePrototype.create(images.folders()), "Files"), true);
310

    
311
        tagTreeSelectionModel = new SingleSelectionModel<Tag>();
312
        tagTreeViewModel = new TagTreeViewModel(tagTreeSelectionModel);
313
        tagTreeView = new TagTreeView(tagTreeViewModel);
314
        
315
        VerticalPanel trees = new VerticalPanel();
316
        trees.add(folderTreeView);
317
        trees.add(tagTreeView);
318
        // Add the left and right panels to the split panel.
319
        splitPanel.setLeftWidget(trees);
320
        splitPanel.setRightWidget(inner);
321
        splitPanel.setSplitPosition("25%");
322
        splitPanel.setSize("100%", "100%");
323
        splitPanel.addStyleName("pithos-splitPanel");
324

    
325
        // Create a dock panel that will contain the menu bar at the top,
326
        // the shortcuts to the left, the status bar at the bottom and the
327
        // right panel taking the rest.
328
        VerticalPanel outer = new VerticalPanel();
329
        outer.add(topPanel);
330
        outer.add(messagePanel);
331
        outer.add(splitPanel);
332
        statusPanel = new StatusPanel(GSS.images);
333
        outer.add(statusPanel);
334
        outer.setWidth("100%");
335
        outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
336

    
337
        outer.setSpacing(4);
338

    
339
        // Hook the window resize event, so that we can adjust the UI.
340
        Window.addResizeHandler(this);
341
        // Clear out the window's built-in margin, because we want to take
342
        // advantage of the entire client area.
343
        Window.setMargin("0px");
344
        // Finally, add the outer panel to the RootPanel, so that it will be
345
        // displayed.
346
        RootPanel.get().add(outer);
347
        // Call the window resized handler to get the initial sizes setup. Doing
348
        // this in a deferred command causes it to occur after all widgets'
349
        // sizes have been computed by the browser.
350
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
351

    
352
            @Override
353
            public void execute() {
354
                onWindowResized(Window.getClientHeight());
355
            }
356
        });
357

    
358
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
359
            @Override
360
            public void execute() {
361
                fetchAccount();
362
            }
363
        });
364
    }
365

    
366
    public void showFiles(Folder f) {
367
        inner.selectTab(0);
368
        if (f.isTrash()) {
369
            fileList.showTrash();
370
        }
371
        else
372
            fileList.showFiles();
373
        Set<File> files = f.getFiles();
374
        Iterator<File> iter = files.iterator();
375
        fetchFile(iter, files);
376
    }
377

    
378
    private void fetchFile(final Iterator<File> iter, final Set<File> files) {
379
        if (iter.hasNext()) {
380
            File file = iter.next();
381
            String path = getApiPath() + username + "/" + file.getContainer() + "/" + file.getPath() + "?format=json";
382
            GetRequest<File> getFile = new GetRequest<File>(File.class, path, file) {
383
                @Override
384
                public void onSuccess(File result) {
385
                    fetchFile(iter, files);
386
                }
387

    
388
                @Override
389
                public void onError(Throwable t) {
390
                    GWT.log("Error getting file", t);
391
                    if (t instanceof RestException)
392
                        GSS.get().displayError("Error getting file: " + ((RestException) t).getHttpStatusText());
393
                    else
394
                        GSS.get().displayError("System error fetching file: " + t.getMessage());
395
                }
396
            };
397
            getFile.setHeader("X-Auth-Token", "0000");
398
            Scheduler.get().scheduleDeferred(getFile);
399
        }
400
        else
401
            fileList.setFiles(new ArrayList<File>(files));
402
    }
403

    
404
    /**
405
         * Parse and store the user credentials to the appropriate fields.
406
         */
407
        private boolean parseUserCredentials() {
408
                Configuration conf = (Configuration) GWT.create(Configuration.class);
409
                String cookie = conf.authCookie();
410
                String auth = Cookies.getCookie(cookie);
411
                if (auth == null) {
412
                        authenticateUser();
413
            return false;
414
        }
415
        else {
416
            String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
417
            if (authSplit.length != 2) {
418
                authenticateUser();
419
                return false;
420
            }
421
            else {
422
                username = authSplit[0];
423
                token = authSplit[1];
424
                return true;
425
            }
426
        }
427
        }
428

    
429
    /**
430
         * Redirect the user to the login page for authentication.
431
         */
432
        protected void authenticateUser() {
433
                Configuration conf = (Configuration) GWT.create(Configuration.class);
434

    
435
//        Window.Location.assign(GWT.getModuleBaseURL() + conf.loginUrl() + "?next=" + Window.Location.getHref());
436
        Cookies.setCookie(conf.authCookie(), "test" + conf.cookieSeparator() + "0000");
437
        Window.Location.assign(GWT.getModuleBaseURL() + "GSS.html");
438
        }
439

    
440
    private void fetchAccount() {
441
        String path = getApiPath() + username + "?format=json";
442

    
443
        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, path) {
444
            @Override
445
            public void onSuccess(AccountResource result) {
446
                account = result;
447
                statusPanel.displayStats(account);
448
                folderTreeViewModel.initialize(account);
449
                inner.selectTab(0);
450
            }
451

    
452
            @Override
453
            public void onError(Throwable t) {
454
                GWT.log("Error getting account", t);
455
                if (t instanceof RestException)
456
                    GSS.get().displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
457
                else
458
                    GSS.get().displayError("System error fetching user data: " + t.getMessage());
459
            }
460
        };
461
        getAccount.setHeader("X-Auth-Token", token);
462
        Scheduler.get().scheduleDeferred(getAccount);
463
    }
464

    
465
        /**
466
         * Clear the cookie and redirect the user to the logout page.
467
         */
468
        void logout() {
469
                Configuration conf = (Configuration) GWT.create(Configuration.class);
470
                String cookie = conf.authCookie();
471
                String domain = Window.Location.getHostName();
472
                String path = Window.Location.getPath();
473
                Cookies.setCookie(cookie, "", null, domain, path, false);
474
        String baseUrl = GWT.getModuleBaseURL();
475
        String homeUrl = baseUrl.substring(0, baseUrl.indexOf(path));
476
                Window.Location.assign(homeUrl + conf.logoutUrl());
477
        }
478

    
479
        /**
480
         * Creates an HTML fragment that places an image & caption together, for use
481
         * in a group header.
482
         *
483
         * @param imageProto an image prototype for an image
484
         * @param caption the group caption
485
         * @return the header HTML fragment
486
         */
487
        private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
488
                String captionHTML = "<table class='caption' cellpadding='0' " 
489
                + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML() 
490
                + "</td><td id =" + caption +" class='rcaption'><b style='white-space:nowrap'>&nbsp;" 
491
                + caption + "</b></td></tr></table>";
492
                return captionHTML;
493
        }
494

    
495
        private void onWindowResized(int height) {
496
                // Adjust the split panel to take up the available room in the window.
497
                int newHeight = height - splitPanel.getAbsoluteTop() - 44;
498
                if (newHeight < 1)
499
                        newHeight = 1;
500
                splitPanel.setHeight("" + newHeight);
501
                inner.setHeight("" + newHeight);
502
        }
503

    
504
        @Override
505
        public void onResize(ResizeEvent event) {
506
                int height = event.getHeight();
507
                onWindowResized(height);
508
        }
509

    
510
        public boolean isFileListShowing() {
511
                int tab = inner.getTabBar().getSelectedTab();
512
                if (tab == 0)
513
                        return true;
514
                return false;
515
        }
516

    
517
        public boolean isSearchResultsShowing() {
518
                int tab = inner.getTabBar().getSelectedTab();
519
                if (tab == 2)
520
                        return true;
521
                return false;
522
        }
523

    
524
        /**
525
         * Make the file list visible.
526
         *
527
         * @param update
528
         */
529
        public void showFileList(boolean update) {
530
                if(update){
531
                        getTreeView().refreshCurrentNode(true);
532
                }
533
                else{
534
                        RestResource currentFolder = getTreeView().getSelection();
535
                        if(currentFolder!=null){
536
                                showFileList(currentFolder);
537
                }
538
                }
539

    
540
        }
541
        
542
        public void showFileList(RestResource r) {
543
                showFileList(r,true);
544
        }
545
        
546
        public void showFileList(RestResource r, boolean clearSelection) {
547
                RestResource currentFolder = r;
548
                if(currentFolder!=null){
549
                        List<FileResource> files = null;
550
                        if (currentFolder instanceof RestResourceWrapper) {
551
                                RestResourceWrapper folder = (RestResourceWrapper) currentFolder;
552
                                files = folder.getResource().getFiles();
553
                        }
554
                }
555
                inner.selectTab(0);
556
        }
557

    
558
        /**
559
         * Display the 'loading' indicator.
560
         */
561
        public void showLoadingIndicator(String message, String path) {
562
                if(path!=null){
563
                        String[] split = path.split("/");
564
                        message = message +" "+URL.decode(split[split.length-1]);
565
                }
566
                topPanel.getLoading().show(message);
567
        }
568

    
569
        /**
570
         * Hide the 'loading' indicator.
571
         */
572
        public void hideLoadingIndicator() {
573
                topPanel.getLoading().hide();
574
        }
575

    
576
        /**
577
         * A native JavaScript method to reach out to the browser's window and
578
         * invoke its resizeTo() method.
579
         *
580
         * @param x the new width
581
         * @param y the new height
582
         */
583
        public static native void resizeTo(int x, int y) /*-{
584
                $wnd.resizeTo(x,y);
585
        }-*/;
586

    
587
        /**
588
         * A helper method that returns true if the user's list is currently visible
589
         * and false if it is hidden.
590
         *
591
         * @return true if the user list is visible
592
         */
593
        public boolean isUserListVisible() {
594
                return inner.getTabBar().getSelectedTab() == 1;
595
        }
596

    
597
        /**
598
         * Display an error message.
599
         *
600
         * @param msg the message to display
601
         */
602
        public void displayError(String msg) {
603
                messagePanel.displayError(msg);
604
        }
605

    
606
        /**
607
         * Display a warning message.
608
         *
609
         * @param msg the message to display
610
         */
611
        public void displayWarning(String msg) {
612
                messagePanel.displayWarning(msg);
613
        }
614

    
615
        /**
616
         * Display an informational message.
617
         *
618
         * @param msg the message to display
619
         */
620
        public void displayInformation(String msg) {
621
                messagePanel.displayInformation(msg);
622
        }
623

    
624
        /**
625
         * Retrieve the folders.
626
         *
627
         * @return the folders
628
         
629
        public Folders getFolders() {
630
                return folders;
631
        }*/
632

    
633
        /**
634
         * Retrieve the currentSelection.
635
         *
636
         * @return the currentSelection
637
         */
638
        public Object getCurrentSelection() {
639
                return currentSelection;
640
        }
641

    
642
        /**
643
         * Modify the currentSelection.
644
         *
645
         * @param newCurrentSelection the currentSelection to set
646
         */
647
        public void setCurrentSelection(Object newCurrentSelection) {
648
                currentSelection = newCurrentSelection;
649
        }
650

    
651
        /**
652
         * Retrieve the fileList.
653
         *
654
         * @return the fileList
655
         */
656
        public FileList getFileList() {
657
                return fileList;
658
        }
659

    
660
        /**
661
         * Retrieve the topPanel.
662
         *
663
         * @return the topPanel
664
         */
665
        TopPanel getTopPanel() {
666
                return topPanel;
667
        }
668

    
669
        /**
670
         * Retrieve the clipboard.
671
         *
672
         * @return the clipboard
673
         */
674
        public Clipboard getClipboard() {
675
                return clipboard;
676
        }
677

    
678
        public StatusPanel getStatusPanel() {
679
                return statusPanel;
680
        }
681

    
682
        /**
683
         * Retrieve the userDetailsPanel.
684
         *
685
         * @return the userDetailsPanel
686
         */
687
        public UserDetailsPanel getUserDetailsPanel() {
688
                return userDetailsPanel;
689
        }
690

    
691
        
692

    
693
        public String getToken() {
694
                return token;
695
        }
696

    
697
        public String getWebDAVPassword() {
698
                return webDAVPassword;
699
        }
700

    
701
        /**
702
         * Retrieve the currentUserResource.
703
         *
704
         * @return the currentUserResource
705
         */
706
        public UserResource getCurrentUserResource() {
707
                return currentUserResource;
708
        }
709

    
710
        /**
711
         * Modify the currentUserResource.
712
         *
713
         * @param newUser the new currentUserResource
714
         */
715
        public void setCurrentUserResource(UserResource newUser) {
716
                currentUserResource = newUser;
717
        }
718

    
719
        public static native void preventIESelection() /*-{
720
                $doc.body.onselectstart = function () { return false; };
721
        }-*/;
722

    
723
        public static native void enableIESelection() /*-{
724
                if ($doc.body.onselectstart != null)
725
                $doc.body.onselectstart = null;
726
        }-*/;
727

    
728
        /**
729
         * @return the absolute path of the API root URL
730
         */
731
        public String getApiPath() {
732
                Configuration conf = (Configuration) GWT.create(Configuration.class);
733
                return conf.apiPath();
734
        }
735

    
736
        /**
737
         * Convert server date to local time according to browser timezone
738
         * and format it according to localized pattern.
739
         * Time is always formatted to 24hr format.
740
         * NB: This assumes that server runs in UTC timezone. Otherwise
741
         * we would need to adjust for server time offset as well.
742
         *
743
         * @param date
744
         * @return String
745
         */
746
        public static String formatLocalDateTime(Date date) {
747
                Date convertedDate = new Date(date.getTime() - date.getTimezoneOffset());
748
                final DateTimeFormat dateFormatter = DateTimeFormat.getShortDateFormat();
749
                final DateTimeFormat timeFormatter = DateTimeFormat.getFormat("HH:mm");
750
                String datePart = dateFormatter.format(convertedDate);
751
                String timePart = timeFormatter.format(convertedDate);
752
                return datePart + " " + timePart;
753
        }
754
        
755
        /**
756
         * History support for folder navigation
757
         * adds a new browser history entry
758
         *
759
         * @param key
760
         */
761
        public void updateHistory(String key){
762
//                Replace any whitespace of the initial string to "+"
763
//                String result = key.replaceAll("\\s","+");
764
//                Add a new browser history entry.
765
//                History.newItem(result);
766
                History.newItem(key);
767
        }
768

    
769
        /**
770
         * This method examines the token input and add a "/" at the end in case it's omitted.
771
         * This happens only in Files/trash/, Files/shared/, Files/others.
772
         *
773
         * @param tokenInput
774
         * @return the formated token with a "/" at the end or the same tokenInput parameter
775
         */
776

    
777
        private String handleSpecialFolderNames(String tokenInput){
778
                List<String> pathsToCheck = Arrays.asList("Files/trash", "Files/shared", "Files/others");
779
                if(pathsToCheck.contains(tokenInput))
780
                        return tokenInput + "/";
781
                return tokenInput;
782

    
783
        }
784

    
785
        /**
786
         * Reject illegal resource names, like '.' or '..' or slashes '/'.
787
         */
788
        static boolean isValidResourceName(String name) {
789
                if (".".equals(name) ||        "..".equals(name) || name.contains("/"))
790
                        return false;
791
                return true;
792
        }
793

    
794
        public void putUserToMap(String _userName, String _userFullName){
795
                userFullNameMap.put(_userName, _userFullName);
796
        }
797

    
798
        public String findUserFullName(String _userName){
799
                return userFullNameMap.get(_userName);
800
        }
801
        public String getUserFullName(String _userName) {
802
                
803
        if (GSS.get().findUserFullName(_userName) == null)
804
                //if there is no userFullName found then the map fills with the given _userName,
805
                //so userFullName = _userName
806
                GSS.get().putUserToMap(_userName, _userName);
807
        else if(GSS.get().findUserFullName(_userName).indexOf('@') != -1){
808
                //if the userFullName = _userName the GetUserCommand updates the userFullName in the map
809
                GetUserCommand guc = new GetUserCommand(_userName);
810
                guc.execute();
811
        }
812
        return GSS.get().findUserFullName(_userName);
813
        }
814
        /**
815
         * Retrieve the treeView.
816
         *
817
         * @return the treeView
818
         */
819
        public CellTreeView getTreeView() {
820
                return treeView;
821
        }
822
        
823
        public void onResourceUpdate(RestResource resource,boolean clearSelection){
824
                if(resource instanceof RestResourceWrapper || resource instanceof OtherUserResource || resource instanceof TrashResource || resource instanceof SharedResource){
825
                        if(getTreeView().getSelection()!=null&&getTreeView().getSelection().getUri().equals(resource.getUri()))
826
                                showFileList(resource,clearSelection);
827
                }
828
                
829
        }
830

    
831
    public void deleteFolder(final Folder folder) {
832
        String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + folder.getPrefix();
833
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
834
        builder.setHeader("If-Modified-Since", "0");
835
        builder.setHeader("X-Auth-Token", getToken());
836
        try {
837
            builder.sendRequest("", new RequestCallback() {
838
                @Override
839
                public void onResponseReceived(Request request, Response response) {
840
                    if (response.getStatusCode() == Response.SC_OK) {
841
                        JSONValue json = JSONParser.parseStrict(response.getText());
842
                        JSONArray array = json.isArray();
843
                        int i = 0;
844
                        if (array != null) {
845
                            deleteObject(folder, i, array);
846
                        }
847
                    }
848
                }
849

    
850
                @Override
851
                public void onError(Request request, Throwable exception) {
852
                    GSS.get().displayError("System error unable to delete folder: " + exception.getMessage());
853
                }
854
            });
855
        }
856
        catch (RequestException e) {
857
        }
858
    }
859

    
860
    public void deleteObject(final Folder folder, final int i, final JSONArray array) {
861
        if (i < array.size()) {
862
            JSONObject o = array.get(i).isObject();
863
            if (o != null && !o.containsKey("subdir")) {
864
                JSONString name = o.get("name").isString();
865
                String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "/" + name.stringValue();
866
                DeleteRequest delete = new DeleteRequest(path) {
867
                    @Override
868
                    public void onSuccess(Resource result) {
869
                        deleteObject(folder, i + 1, array);
870
                    }
871

    
872
                    @Override
873
                    public void onError(Throwable t) {
874
                        GWT.log("", t);
875
                        GSS.get().displayError("System error unable to delete folder: " + t.getMessage());
876
                    }
877
                };
878
                delete.setHeader("X-Auth-Token", getToken());
879
                Scheduler.get().scheduleDeferred(delete);
880
            }
881
            else {
882
                String subdir = o.get("subdir").isString().stringValue();
883
                subdir = subdir.substring(0, subdir.length() - 1);
884
                String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + subdir;
885
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
886
                builder.setHeader("If-Modified-Since", "0");
887
                builder.setHeader("X-Auth-Token", getToken());
888
                try {
889
                    builder.sendRequest("", new RequestCallback() {
890
                        @Override
891
                        public void onResponseReceived(Request request, Response response) {
892
                            if (response.getStatusCode() == Response.SC_OK) {
893
                                JSONValue json = JSONParser.parseStrict(response.getText());
894
                                JSONArray array2 = json.isArray();
895
                                if (array2 != null) {
896
                                    int l = array.size();
897
                                    for (int j=0; j<array2.size(); j++) {
898
                                        array.set(l++, array2.get(j));
899
                                    }
900
                                }
901
                                deleteObject(folder, i + 1, array);
902
                            }
903
                        }
904

    
905
                        @Override
906
                        public void onError(Request request, Throwable exception) {
907
                            GSS.get().displayError("System error unable to delete folder: " + exception.getMessage());
908
                        }
909
                    });
910
                }
911
                catch (RequestException e) {
912
                }
913
            }
914
        }
915
        else {
916
            String prefix = folder.getPrefix();
917
            String path = getApiPath() + getUsername() + "/" + folder.getContainer() + (prefix.length() == 0 ? "" : "/" + prefix);
918
            DeleteRequest deleteFolder = new DeleteRequest(path) {
919
                @Override
920
                public void onSuccess(Resource result) {
921
                    updateFolder(folder.getParent());
922
                }
923

    
924
                @Override
925
                public void onError(Throwable t) {
926
                    GWT.log("", t);
927
                    if (t instanceof RestException) {
928
                        displayError("Unable to delete folder: "+((RestException) t).getHttpStatusText());
929
                    }
930
                    else
931
                        GSS.get().displayError("System error unable to delete folder: " + t.getMessage());
932
                }
933
            };
934
            deleteFolder.setHeader("X-Auth-Token", getToken());
935
            Scheduler.get().scheduleDeferred(deleteFolder);
936
        }
937
    }
938

    
939
    public FolderTreeView getFolderTreeView() {
940
        return folderTreeView;
941
    }
942

    
943
    public void copyFiles(final Iterator<File> iter, final String targetUri, final Command callback) {
944
        if (iter.hasNext()) {
945
            File file = iter.next();
946
            String path = getApiPath() + getUsername() + targetUri + "/" + file.getName();
947
            PutRequest copyFile = new PutRequest(path) {
948
                @Override
949
                public void onSuccess(Resource result) {
950
                    copyFiles(iter, targetUri, callback);
951
                }
952

    
953
                @Override
954
                public void onError(Throwable t) {
955
                    GWT.log("", t);
956
                    if (t instanceof RestException) {
957
                        GSS.get().displayError("Unable to copy file: " + ((RestException) t).getHttpStatusText());
958
                    }
959
                    else
960
                        GSS.get().displayError("System error unable to copy file: "+t.getMessage());
961
                }
962
            };
963
            copyFile.setHeader("X-Auth-Token", getToken());
964
            copyFile.setHeader("X-Copy-From", file.getUri());
965
            Scheduler.get().scheduleDeferred(copyFile);
966
        }
967
        else  if (callback != null) {
968
            callback.execute();
969
        }
970
    }
971

    
972
    public void copySubfolders(final Iterator<Folder> iter, final String targetUri, final Command callback) {
973
        if (iter.hasNext()) {
974
            final Folder f = iter.next();
975
            copyFolder(f, targetUri, callback);
976
        }
977
        else  if (callback != null) {
978
            callback.execute();
979
        }
980
    }
981

    
982
    public void copyFolder(final Folder f, final String targetUri, final Command callback) {
983
        String path = getApiPath() + getUsername() + targetUri + "/" + f.getName();
984
        PutRequest createFolder = new PutRequest(path) {
985
            @Override
986
            public void onSuccess(Resource result) {
987
                Iterator<File> iter = f.getFiles().iterator();
988
                copyFiles(iter, targetUri + "/" + f.getName(), new Command() {
989
                    @Override
990
                    public void execute() {
991
                        Iterator<Folder> iterf = f.getSubfolders().iterator();
992
                        copySubfolders(iterf, targetUri + "/" + f.getName(), new Command() {
993
                            @Override
994
                            public void execute() {
995
                                callback.execute();
996
                            }
997
                        });
998
                    }
999
                });
1000
            }
1001

    
1002
            @Override
1003
            public void onError(Throwable t) {
1004
                GWT.log("", t);
1005
                if (t instanceof RestException) {
1006
                    displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());
1007
                }
1008
                else
1009
                    displayError("System error creating folder:" + t.getMessage());
1010
            }
1011
        };
1012
        createFolder.setHeader("X-Auth-Token", getToken());
1013
        createFolder.setHeader("Accept", "*/*");
1014
        createFolder.setHeader("Content-Length", "0");
1015
        createFolder.setHeader("Content-Type", "application/folder");
1016
        Scheduler.get().scheduleDeferred(createFolder);
1017
    }
1018
}