Statistics
| Branch: | Tag: | Revision:

root / web_client / src / gr / grnet / pithos / web / client / Pithos.java @ 3da18014

History | View | Annotate | Download (34.5 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.SelectionChangeEvent.Handler;
52
import com.google.gwt.view.client.SingleSelectionModel;
53
import gr.grnet.pithos.web.client.commands.GetUserCommand;
54
import gr.grnet.pithos.web.client.foldertree.AccountResource;
55
import gr.grnet.pithos.web.client.foldertree.File;
56
import gr.grnet.pithos.web.client.foldertree.Folder;
57
import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
58
import gr.grnet.pithos.web.client.foldertree.FolderTreeViewModel;
59
import gr.grnet.pithos.web.client.foldertree.Resource;
60
import gr.grnet.pithos.web.client.rest.DeleteRequest;
61
import gr.grnet.pithos.web.client.rest.GetRequest;
62
import gr.grnet.pithos.web.client.rest.PutRequest;
63
import gr.grnet.pithos.web.client.rest.RestException;
64
import gr.grnet.pithos.web.client.rest.resource.FileResource;
65
import gr.grnet.pithos.web.client.rest.resource.OtherUserResource;
66
import gr.grnet.pithos.web.client.rest.resource.RestResource;
67
import gr.grnet.pithos.web.client.rest.resource.RestResourceWrapper;
68
import gr.grnet.pithos.web.client.rest.resource.SharedResource;
69
import gr.grnet.pithos.web.client.rest.resource.TrashResource;
70
import gr.grnet.pithos.web.client.rest.resource.UserResource;
71

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

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

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

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

    
115
        public static final int VISIBLE_FILE_COUNT = 25;
116

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

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

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

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

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

    
139
    public void updateTag(Tag t) {
140
        tagTreeView.updateTag(t);
141
    }
142

    
143
    public void updateTags() {
144
        tagTreeViewModel.initialize(account);
145
    }
146

    
147
    /**
148
         * An aggregate image bundle that pulls together all the images for this
149
         * application into a single bundle.
150
         */
151
        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 {
152

    
153
                @Source("gr/grnet/pithos/resources/document.png")
154
                ImageResource folders();
155

    
156
                @Source("gr/grnet/pithos/resources/edit_group_22.png")
157
                ImageResource groups();
158

    
159
                @Source("gr/grnet/pithos/resources/search.png")
160
                ImageResource search();
161
        }
162

    
163
        /**
164
         * The single Pithos instance.
165
         */
166
        private static Pithos singleton;
167

    
168
        /**
169
         * Gets the singleton Pithos instance.
170
         *
171
         * @return the Pithos object
172
         */
173
        public static Pithos get() {
174
                if (Pithos.singleton == null)
175
                        Pithos.singleton = new Pithos();
176
                return Pithos.singleton;
177
        }
178

    
179
        /**
180
         * The Application Clipboard implementation;
181
         */
182
        private Clipboard clipboard = new Clipboard();
183

    
184
        private UserResource currentUserResource;
185

    
186
        /**
187
         * The top panel that contains the menu bar.
188
         */
189
        private TopPanel topPanel;
190

    
191
        /**
192
         * The panel that contains the various system messages.
193
         */
194
        private MessagePanel messagePanel = new MessagePanel(Pithos.images);
195

    
196
        /**
197
         * The bottom panel that contains the status bar.
198
         */
199
        private StatusPanel statusPanel = null;
200

    
201
        /**
202
         * The top right panel that displays the logged in user details
203
         */
204
        private UserDetailsPanel userDetailsPanel = new UserDetailsPanel();
205

    
206
        /**
207
         * The file list widget.
208
         */
209
        private FileList fileList;
210

    
211
        /**
212
         * The tab panel that occupies the right side of the screen.
213
         */
214
        private TabPanel inner = new DecoratedTabPanel(){
215
                
216
//                public void onBrowserEvent(com.google.gwt.user.client.Event event) {
217
//                        if (DOM.eventGetType(event) == Event.ONCONTEXTMENU){
218
//                                if(isFileListShowing()){
219
//                                        getFileList().showContextMenu(event);
220
//                                }
221
//                        }
222
//                };
223
        };
224

    
225

    
226
        /**
227
         * The split panel that will contain the left and right panels.
228
         */
229
        private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
230

    
231
        /**
232
         * The widget that displays the tree of folders.
233
         */
234
        
235
        private CellTreeView treeView = null;
236
        /**
237
         * The currently selected item in the application, for use by the Edit menu
238
         * commands. Potential types are Folder, File, User and Group.
239
         */
240
        private Object currentSelection;
241

    
242

    
243
        /**
244
         * The WebDAV password of the current user
245
         */
246
        private String webDAVPassword;
247

    
248
        public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
249

    
250
    private String username = null;
251

    
252
    /**
253
     * The authentication token of the current user.
254
     */
255
    private String token;
256

    
257
    private SingleSelectionModel<Folder> folderTreeSelectionModel;
258
    private FolderTreeViewModel folderTreeViewModel;
259
    private FolderTreeView folderTreeView;
260

    
261
    private SingleSelectionModel<Tag> tagTreeSelectionModel;
262
    private TagTreeViewModel tagTreeViewModel;
263
    private TagTreeView tagTreeView;
264

    
265
    private AccountResource account;
266

    
267
        @Override
268
        public void onModuleLoad() {
269
                // Initialize the singleton before calling the constructors of the
270
                // various widgets that might call Pithos.get().
271
                singleton = this;
272
                if (parseUserCredentials())
273
            initialize();
274
        }
275

    
276
    private void initialize() {
277
        topPanel = new TopPanel(Pithos.images);
278
        topPanel.setWidth("100%");
279

    
280
        messagePanel.setWidth("100%");
281
        messagePanel.setVisible(false);
282

    
283

    
284
        // Inner contains the various lists.
285
        inner.sinkEvents(Event.ONCONTEXTMENU);
286
        inner.setAnimationEnabled(true);
287
        inner.getTabBar().addStyleName("pithos-MainTabBar");
288
        inner.getDeckPanel().addStyleName("pithos-MainTabPanelBottom");
289

    
290
        inner.setWidth("100%");
291

    
292
        inner.addSelectionHandler(new SelectionHandler<Integer>() {
293

    
294
            @Override
295
            public void onSelection(SelectionEvent<Integer> event) {
296
                int tabIndex = event.getSelectedItem();
297
                switch (tabIndex) {
298
                    case 0:
299
                        fileList.updateCurrentlyShowingStats();
300
                        break;
301
                }
302
            }
303
        });
304

    
305
        folderTreeSelectionModel = new SingleSelectionModel<Folder>();
306
        folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
307
            @Override
308
            public void onSelectionChange(SelectionChangeEvent event) {
309
                if (folderTreeSelectionModel.getSelectedObject() != null) {
310
                    tagTreeSelectionModel.setSelected(tagTreeSelectionModel.getSelectedObject(), false);
311
                    Folder f = folderTreeSelectionModel.getSelectedObject();
312
                    updateFolder(f);
313
                }
314
            }
315
        });
316

    
317
        folderTreeViewModel = new FolderTreeViewModel(folderTreeSelectionModel);
318
        folderTreeView = new FolderTreeView(folderTreeViewModel);
319

    
320
        fileList = new FileList(images, folderTreeView);
321
        inner.add(fileList, createHeaderHTML(AbstractImagePrototype.create(images.folders()), "Files"), true);
322

    
323
        tagTreeSelectionModel = new SingleSelectionModel<Tag>();
324
        tagTreeSelectionModel.addSelectionChangeHandler(new Handler() {
325
            @Override
326
            public void onSelectionChange(SelectionChangeEvent event) {
327
                if (tagTreeSelectionModel.getSelectedObject() != null) {
328
                    folderTreeSelectionModel.setSelected(folderTreeSelectionModel.getSelectedObject(), false);
329
                    Tag t = tagTreeSelectionModel.getSelectedObject();
330
                    updateTag(t);
331
                }
332
            }
333
        });
334
        tagTreeViewModel = new TagTreeViewModel(tagTreeSelectionModel);
335
        tagTreeView = new TagTreeView(tagTreeViewModel);
336

    
337
        VerticalPanel trees = new VerticalPanel();
338
        trees.add(folderTreeView);
339
        trees.add(tagTreeView);
340
        // Add the left and right panels to the split panel.
341
        splitPanel.setLeftWidget(trees);
342
        splitPanel.setRightWidget(inner);
343
        splitPanel.setSplitPosition("25%");
344
        splitPanel.setSize("100%", "100%");
345
        splitPanel.addStyleName("pithos-splitPanel");
346

    
347
        // Create a dock panel that will contain the menu bar at the top,
348
        // the shortcuts to the left, the status bar at the bottom and the
349
        // right panel taking the rest.
350
        VerticalPanel outer = new VerticalPanel();
351
        outer.add(topPanel);
352
        outer.add(messagePanel);
353
        outer.add(splitPanel);
354
        statusPanel = new StatusPanel(Pithos.images);
355
        outer.add(statusPanel);
356
        outer.setWidth("100%");
357
        outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
358

    
359
        outer.setSpacing(4);
360

    
361
        // Hook the window resize event, so that we can adjust the UI.
362
        Window.addResizeHandler(this);
363
        // Clear out the window's built-in margin, because we want to take
364
        // advantage of the entire client area.
365
        Window.setMargin("0px");
366
        // Finally, add the outer panel to the RootPanel, so that it will be
367
        // displayed.
368
        RootPanel.get().add(outer);
369
        // Call the window resized handler to get the initial sizes setup. Doing
370
        // this in a deferred command causes it to occur after all widgets'
371
        // sizes have been computed by the browser.
372
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
373

    
374
            @Override
375
            public void execute() {
376
                onWindowResized(Window.getClientHeight());
377
            }
378
        });
379

    
380
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
381
            @Override
382
            public void execute() {
383
                fetchAccount();
384
            }
385
        });
386
    }
387

    
388
    public void showFiles(Folder f) {
389
        inner.selectTab(0);
390
        if (f.isTrash()) {
391
            fileList.showTrash();
392
        }
393
        else
394
            fileList.showFiles();
395
        Set<File> files = f.getFiles();
396
        showFiles(files);
397
    }
398

    
399
    public void showFiles(Set<File> files) {
400
        //Iterator<File> iter = files.iterator();
401
        //fetchFile(iter, files);
402
        fileList.setFiles(new ArrayList<File>(files));
403
    }
404

    
405
    private void fetchFile(final Iterator<File> iter, final Set<File> files) {
406
        if (iter.hasNext()) {
407
            File file = iter.next();
408
            String path = getApiPath() + username + "/" + file.getContainer() + "/" + file.getPath() + "?format=json";
409
            GetRequest<File> getFile = new GetRequest<File>(File.class, path, file) {
410
                @Override
411
                public void onSuccess(File result) {
412
                    fetchFile(iter, files);
413
                }
414

    
415
                @Override
416
                public void onError(Throwable t) {
417
                    GWT.log("Error getting file", t);
418
                    if (t instanceof RestException)
419
                        Pithos.get().displayError("Error getting file: " + ((RestException) t).getHttpStatusText());
420
                    else
421
                        Pithos.get().displayError("System error fetching file: " + t.getMessage());
422
                }
423
            };
424
            getFile.setHeader("X-Auth-Token", "0000");
425
            Scheduler.get().scheduleDeferred(getFile);
426
        }
427
        else
428
            fileList.setFiles(new ArrayList<File>(files));
429
    }
430

    
431
    /**
432
         * Parse and store the user credentials to the appropriate fields.
433
         */
434
        private boolean parseUserCredentials() {
435
                Configuration conf = (Configuration) GWT.create(Configuration.class);
436
                String cookie = conf.authCookie();
437
                String auth = Cookies.getCookie(cookie);
438
                if (auth == null) {
439
                        authenticateUser();
440
            return false;
441
        }
442
        else {
443
            String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
444
            if (authSplit.length != 2) {
445
                authenticateUser();
446
                return false;
447
            }
448
            else {
449
                username = authSplit[0];
450
                token = authSplit[1];
451
                return true;
452
            }
453
        }
454
        }
455

    
456
    /**
457
         * Redirect the user to the login page for authentication.
458
         */
459
        protected void authenticateUser() {
460
                Configuration conf = (Configuration) GWT.create(Configuration.class);
461

    
462
//        Window.Location.assign(GWT.getModuleBaseURL() + conf.loginUrl() + "?next=" + Window.Location.getHref());
463
        Cookies.setCookie(conf.authCookie(), "test" + conf.cookieSeparator() + "0000");
464
        Window.Location.assign(GWT.getModuleBaseURL() + "Pithos.html");
465
        }
466

    
467
    private void fetchAccount() {
468
        String path = getApiPath() + username + "?format=json";
469

    
470
        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, path) {
471
            @Override
472
            public void onSuccess(AccountResource result) {
473
                account = result;
474
                statusPanel.displayStats(account);
475
                folderTreeViewModel.initialize(account);
476
                inner.selectTab(0);
477
            }
478

    
479
            @Override
480
            public void onError(Throwable t) {
481
                GWT.log("Error getting account", t);
482
                if (t instanceof RestException)
483
                    Pithos.get().displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
484
                else
485
                    Pithos.get().displayError("System error fetching user data: " + t.getMessage());
486
            }
487
        };
488
        getAccount.setHeader("X-Auth-Token", token);
489
        Scheduler.get().scheduleDeferred(getAccount);
490
    }
491

    
492
        /**
493
         * Clear the cookie and redirect the user to the logout page.
494
         */
495
        void logout() {
496
                Configuration conf = (Configuration) GWT.create(Configuration.class);
497
                String cookie = conf.authCookie();
498
                String domain = Window.Location.getHostName();
499
                String path = Window.Location.getPath();
500
                Cookies.setCookie(cookie, "", null, domain, path, false);
501
        String baseUrl = GWT.getModuleBaseURL();
502
        String homeUrl = baseUrl.substring(0, baseUrl.indexOf(path));
503
                Window.Location.assign(homeUrl + conf.logoutUrl());
504
        }
505

    
506
        /**
507
         * Creates an HTML fragment that places an image & caption together, for use
508
         * in a group header.
509
         *
510
         * @param imageProto an image prototype for an image
511
         * @param caption the group caption
512
         * @return the header HTML fragment
513
         */
514
        private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
515
                String captionHTML = "<table class='caption' cellpadding='0' " 
516
                + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML() 
517
                + "</td><td id =" + caption +" class='rcaption'><b style='white-space:nowrap'>&nbsp;" 
518
                + caption + "</b></td></tr></table>";
519
                return captionHTML;
520
        }
521

    
522
        private void onWindowResized(int height) {
523
                // Adjust the split panel to take up the available room in the window.
524
                int newHeight = height - splitPanel.getAbsoluteTop() - 44;
525
                if (newHeight < 1)
526
                        newHeight = 1;
527
                splitPanel.setHeight("" + newHeight);
528
                inner.setHeight("" + newHeight);
529
        }
530

    
531
        @Override
532
        public void onResize(ResizeEvent event) {
533
                int height = event.getHeight();
534
                onWindowResized(height);
535
        }
536

    
537
        public boolean isFileListShowing() {
538
                int tab = inner.getTabBar().getSelectedTab();
539
                if (tab == 0)
540
                        return true;
541
                return false;
542
        }
543

    
544
        public boolean isSearchResultsShowing() {
545
                int tab = inner.getTabBar().getSelectedTab();
546
                if (tab == 2)
547
                        return true;
548
                return false;
549
        }
550

    
551
        /**
552
         * Make the file list visible.
553
         *
554
         * @param update
555
         */
556
        public void showFileList(boolean update) {
557
                if(update){
558
                        getTreeView().refreshCurrentNode(true);
559
                }
560
                else{
561
                        RestResource currentFolder = getTreeView().getSelection();
562
                        if(currentFolder!=null){
563
                                showFileList(currentFolder);
564
                }
565
                }
566

    
567
        }
568
        
569
        public void showFileList(RestResource r) {
570
                showFileList(r,true);
571
        }
572
        
573
        public void showFileList(RestResource r, boolean clearSelection) {
574
                RestResource currentFolder = r;
575
                if(currentFolder!=null){
576
                        List<FileResource> files = null;
577
                        if (currentFolder instanceof RestResourceWrapper) {
578
                                RestResourceWrapper folder = (RestResourceWrapper) currentFolder;
579
                                files = folder.getResource().getFiles();
580
                        }
581
                }
582
                inner.selectTab(0);
583
        }
584

    
585
        /**
586
         * Display the 'loading' indicator.
587
         */
588
        public void showLoadingIndicator(String message, String path) {
589
                if(path!=null){
590
                        String[] split = path.split("/");
591
                        message = message +" "+URL.decode(split[split.length-1]);
592
                }
593
                topPanel.getLoading().show(message);
594
        }
595

    
596
        /**
597
         * Hide the 'loading' indicator.
598
         */
599
        public void hideLoadingIndicator() {
600
                topPanel.getLoading().hide();
601
        }
602

    
603
        /**
604
         * A native JavaScript method to reach out to the browser's window and
605
         * invoke its resizeTo() method.
606
         *
607
         * @param x the new width
608
         * @param y the new height
609
         */
610
        public static native void resizeTo(int x, int y) /*-{
611
                $wnd.resizeTo(x,y);
612
        }-*/;
613

    
614
        /**
615
         * A helper method that returns true if the user's list is currently visible
616
         * and false if it is hidden.
617
         *
618
         * @return true if the user list is visible
619
         */
620
        public boolean isUserListVisible() {
621
                return inner.getTabBar().getSelectedTab() == 1;
622
        }
623

    
624
        /**
625
         * Display an error message.
626
         *
627
         * @param msg the message to display
628
         */
629
        public void displayError(String msg) {
630
                messagePanel.displayError(msg);
631
        }
632

    
633
        /**
634
         * Display a warning message.
635
         *
636
         * @param msg the message to display
637
         */
638
        public void displayWarning(String msg) {
639
                messagePanel.displayWarning(msg);
640
        }
641

    
642
        /**
643
         * Display an informational message.
644
         *
645
         * @param msg the message to display
646
         */
647
        public void displayInformation(String msg) {
648
                messagePanel.displayInformation(msg);
649
        }
650

    
651
        /**
652
         * Retrieve the folders.
653
         *
654
         * @return the folders
655
         
656
        public Folders getFolders() {
657
                return folders;
658
        }*/
659

    
660
        /**
661
         * Retrieve the currentSelection.
662
         *
663
         * @return the currentSelection
664
         */
665
        public Object getCurrentSelection() {
666
                return currentSelection;
667
        }
668

    
669
        /**
670
         * Modify the currentSelection.
671
         *
672
         * @param newCurrentSelection the currentSelection to set
673
         */
674
        public void setCurrentSelection(Object newCurrentSelection) {
675
                currentSelection = newCurrentSelection;
676
        }
677

    
678
        /**
679
         * Retrieve the fileList.
680
         *
681
         * @return the fileList
682
         */
683
        public FileList getFileList() {
684
                return fileList;
685
        }
686

    
687
        /**
688
         * Retrieve the topPanel.
689
         *
690
         * @return the topPanel
691
         */
692
        TopPanel getTopPanel() {
693
                return topPanel;
694
        }
695

    
696
        /**
697
         * Retrieve the clipboard.
698
         *
699
         * @return the clipboard
700
         */
701
        public Clipboard getClipboard() {
702
                return clipboard;
703
        }
704

    
705
        public StatusPanel getStatusPanel() {
706
                return statusPanel;
707
        }
708

    
709
        /**
710
         * Retrieve the userDetailsPanel.
711
         *
712
         * @return the userDetailsPanel
713
         */
714
        public UserDetailsPanel getUserDetailsPanel() {
715
                return userDetailsPanel;
716
        }
717

    
718
        
719

    
720
        public String getToken() {
721
                return token;
722
        }
723

    
724
        public String getWebDAVPassword() {
725
                return webDAVPassword;
726
        }
727

    
728
        /**
729
         * Retrieve the currentUserResource.
730
         *
731
         * @return the currentUserResource
732
         */
733
        public UserResource getCurrentUserResource() {
734
                return currentUserResource;
735
        }
736

    
737
        /**
738
         * Modify the currentUserResource.
739
         *
740
         * @param newUser the new currentUserResource
741
         */
742
        public void setCurrentUserResource(UserResource newUser) {
743
                currentUserResource = newUser;
744
        }
745

    
746
        public static native void preventIESelection() /*-{
747
                $doc.body.onselectstart = function () { return false; };
748
        }-*/;
749

    
750
        public static native void enableIESelection() /*-{
751
                if ($doc.body.onselectstart != null)
752
                $doc.body.onselectstart = null;
753
        }-*/;
754

    
755
        /**
756
         * @return the absolute path of the API root URL
757
         */
758
        public String getApiPath() {
759
                Configuration conf = (Configuration) GWT.create(Configuration.class);
760
                return conf.apiPath();
761
        }
762

    
763
        /**
764
         * Convert server date to local time according to browser timezone
765
         * and format it according to localized pattern.
766
         * Time is always formatted to 24hr format.
767
         * NB: This assumes that server runs in UTC timezone. Otherwise
768
         * we would need to adjust for server time offset as well.
769
         *
770
         * @param date
771
         * @return String
772
         */
773
        public static String formatLocalDateTime(Date date) {
774
                Date convertedDate = new Date(date.getTime() - date.getTimezoneOffset());
775
                final DateTimeFormat dateFormatter = DateTimeFormat.getShortDateFormat();
776
                final DateTimeFormat timeFormatter = DateTimeFormat.getFormat("HH:mm");
777
                String datePart = dateFormatter.format(convertedDate);
778
                String timePart = timeFormatter.format(convertedDate);
779
                return datePart + " " + timePart;
780
        }
781
        
782
        /**
783
         * History support for folder navigation
784
         * adds a new browser history entry
785
         *
786
         * @param key
787
         */
788
        public void updateHistory(String key){
789
//                Replace any whitespace of the initial string to "+"
790
//                String result = key.replaceAll("\\s","+");
791
//                Add a new browser history entry.
792
//                History.newItem(result);
793
                History.newItem(key);
794
        }
795

    
796
        /**
797
         * This method examines the token input and add a "/" at the end in case it's omitted.
798
         * This happens only in Files/trash/, Files/shared/, Files/others.
799
         *
800
         * @param tokenInput
801
         * @return the formated token with a "/" at the end or the same tokenInput parameter
802
         */
803

    
804
        private String handleSpecialFolderNames(String tokenInput){
805
                List<String> pathsToCheck = Arrays.asList("Files/trash", "Files/shared", "Files/others");
806
                if(pathsToCheck.contains(tokenInput))
807
                        return tokenInput + "/";
808
                return tokenInput;
809

    
810
        }
811

    
812
        /**
813
         * Reject illegal resource names, like '.' or '..' or slashes '/'.
814
         */
815
        static boolean isValidResourceName(String name) {
816
                if (".".equals(name) ||        "..".equals(name) || name.contains("/"))
817
                        return false;
818
                return true;
819
        }
820

    
821
        public void putUserToMap(String _userName, String _userFullName){
822
                userFullNameMap.put(_userName, _userFullName);
823
        }
824

    
825
        public String findUserFullName(String _userName){
826
                return userFullNameMap.get(_userName);
827
        }
828
        public String getUserFullName(String _userName) {
829
                
830
        if (Pithos.get().findUserFullName(_userName) == null)
831
                //if there is no userFullName found then the map fills with the given _userName,
832
                //so userFullName = _userName
833
                Pithos.get().putUserToMap(_userName, _userName);
834
        else if(Pithos.get().findUserFullName(_userName).indexOf('@') != -1){
835
                //if the userFullName = _userName the GetUserCommand updates the userFullName in the map
836
                GetUserCommand guc = new GetUserCommand(_userName);
837
                guc.execute();
838
        }
839
        return Pithos.get().findUserFullName(_userName);
840
        }
841
        /**
842
         * Retrieve the treeView.
843
         *
844
         * @return the treeView
845
         */
846
        public CellTreeView getTreeView() {
847
                return treeView;
848
        }
849
        
850
        public void onResourceUpdate(RestResource resource,boolean clearSelection){
851
                if(resource instanceof RestResourceWrapper || resource instanceof OtherUserResource || resource instanceof TrashResource || resource instanceof SharedResource){
852
                        if(getTreeView().getSelection()!=null&&getTreeView().getSelection().getUri().equals(resource.getUri()))
853
                                showFileList(resource,clearSelection);
854
                }
855
                
856
        }
857

    
858
    public void deleteFolder(final Folder folder) {
859
        String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + folder.getPrefix();
860
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
861
        builder.setHeader("If-Modified-Since", "0");
862
        builder.setHeader("X-Auth-Token", getToken());
863
        try {
864
            builder.sendRequest("", new RequestCallback() {
865
                @Override
866
                public void onResponseReceived(Request request, Response response) {
867
                    if (response.getStatusCode() == Response.SC_OK) {
868
                        JSONValue json = JSONParser.parseStrict(response.getText());
869
                        JSONArray array = json.isArray();
870
                        int i = 0;
871
                        if (array != null) {
872
                            deleteObject(folder, i, array);
873
                        }
874
                    }
875
                }
876

    
877
                @Override
878
                public void onError(Request request, Throwable exception) {
879
                    Pithos.get().displayError("System error unable to delete folder: " + exception.getMessage());
880
                }
881
            });
882
        }
883
        catch (RequestException e) {
884
        }
885
    }
886

    
887
    public void deleteObject(final Folder folder, final int i, final JSONArray array) {
888
        if (i < array.size()) {
889
            JSONObject o = array.get(i).isObject();
890
            if (o != null && !o.containsKey("subdir")) {
891
                JSONString name = o.get("name").isString();
892
                String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "/" + name.stringValue();
893
                DeleteRequest delete = new DeleteRequest(path) {
894
                    @Override
895
                    public void onSuccess(Resource result) {
896
                        deleteObject(folder, i + 1, array);
897
                    }
898

    
899
                    @Override
900
                    public void onError(Throwable t) {
901
                        GWT.log("", t);
902
                        Pithos.get().displayError("System error unable to delete folder: " + t.getMessage());
903
                    }
904
                };
905
                delete.setHeader("X-Auth-Token", getToken());
906
                Scheduler.get().scheduleDeferred(delete);
907
            }
908
            else {
909
                String subdir = o.get("subdir").isString().stringValue();
910
                subdir = subdir.substring(0, subdir.length() - 1);
911
                String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + subdir;
912
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
913
                builder.setHeader("If-Modified-Since", "0");
914
                builder.setHeader("X-Auth-Token", getToken());
915
                try {
916
                    builder.sendRequest("", new RequestCallback() {
917
                        @Override
918
                        public void onResponseReceived(Request request, Response response) {
919
                            if (response.getStatusCode() == Response.SC_OK) {
920
                                JSONValue json = JSONParser.parseStrict(response.getText());
921
                                JSONArray array2 = json.isArray();
922
                                if (array2 != null) {
923
                                    int l = array.size();
924
                                    for (int j=0; j<array2.size(); j++) {
925
                                        array.set(l++, array2.get(j));
926
                                    }
927
                                }
928
                                deleteObject(folder, i + 1, array);
929
                            }
930
                        }
931

    
932
                        @Override
933
                        public void onError(Request request, Throwable exception) {
934
                            Pithos.get().displayError("System error unable to delete folder: " + exception.getMessage());
935
                        }
936
                    });
937
                }
938
                catch (RequestException e) {
939
                }
940
            }
941
        }
942
        else {
943
            String prefix = folder.getPrefix();
944
            String path = getApiPath() + getUsername() + "/" + folder.getContainer() + (prefix.length() == 0 ? "" : "/" + prefix);
945
            DeleteRequest deleteFolder = new DeleteRequest(path) {
946
                @Override
947
                public void onSuccess(Resource result) {
948
                    updateFolder(folder.getParent());
949
                }
950

    
951
                @Override
952
                public void onError(Throwable t) {
953
                    GWT.log("", t);
954
                    if (t instanceof RestException) {
955
                        displayError("Unable to delete folder: "+((RestException) t).getHttpStatusText());
956
                    }
957
                    else
958
                        Pithos.get().displayError("System error unable to delete folder: " + t.getMessage());
959
                }
960
            };
961
            deleteFolder.setHeader("X-Auth-Token", getToken());
962
            Scheduler.get().scheduleDeferred(deleteFolder);
963
        }
964
    }
965

    
966
    public FolderTreeView getFolderTreeView() {
967
        return folderTreeView;
968
    }
969

    
970
    public void copyFiles(final Iterator<File> iter, final String targetUri, final Command callback) {
971
        if (iter.hasNext()) {
972
            File file = iter.next();
973
            String path = getApiPath() + getUsername() + targetUri + "/" + file.getName();
974
            PutRequest copyFile = new PutRequest(path) {
975
                @Override
976
                public void onSuccess(Resource result) {
977
                    copyFiles(iter, targetUri, callback);
978
                }
979

    
980
                @Override
981
                public void onError(Throwable t) {
982
                    GWT.log("", t);
983
                    if (t instanceof RestException) {
984
                        Pithos.get().displayError("Unable to copy file: " + ((RestException) t).getHttpStatusText());
985
                    }
986
                    else
987
                        Pithos.get().displayError("System error unable to copy file: "+t.getMessage());
988
                }
989
            };
990
            copyFile.setHeader("X-Auth-Token", getToken());
991
            copyFile.setHeader("X-Copy-From", file.getUri());
992
            Scheduler.get().scheduleDeferred(copyFile);
993
        }
994
        else  if (callback != null) {
995
            callback.execute();
996
        }
997
    }
998

    
999
    public void copySubfolders(final Iterator<Folder> iter, final String targetUri, final Command callback) {
1000
        if (iter.hasNext()) {
1001
            final Folder f = iter.next();
1002
            copyFolder(f, targetUri, callback);
1003
        }
1004
        else  if (callback != null) {
1005
            callback.execute();
1006
        }
1007
    }
1008

    
1009
    public void copyFolder(final Folder f, final String targetUri, final Command callback) {
1010
        String path = getApiPath() + getUsername() + targetUri + "/" + f.getName();
1011
        PutRequest createFolder = new PutRequest(path) {
1012
            @Override
1013
            public void onSuccess(Resource result) {
1014
                Iterator<File> iter = f.getFiles().iterator();
1015
                copyFiles(iter, targetUri + "/" + f.getName(), new Command() {
1016
                    @Override
1017
                    public void execute() {
1018
                        Iterator<Folder> iterf = f.getSubfolders().iterator();
1019
                        copySubfolders(iterf, targetUri + "/" + f.getName(), new Command() {
1020
                            @Override
1021
                            public void execute() {
1022
                                callback.execute();
1023
                            }
1024
                        });
1025
                    }
1026
                });
1027
            }
1028

    
1029
            @Override
1030
            public void onError(Throwable t) {
1031
                GWT.log("", t);
1032
                if (t instanceof RestException) {
1033
                    displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());
1034
                }
1035
                else
1036
                    displayError("System error creating folder:" + t.getMessage());
1037
            }
1038
        };
1039
        createFolder.setHeader("X-Auth-Token", getToken());
1040
        createFolder.setHeader("Accept", "*/*");
1041
        createFolder.setHeader("Content-Length", "0");
1042
        createFolder.setHeader("Content-Type", "application/folder");
1043
        Scheduler.get().scheduleDeferred(createFolder);
1044
    }
1045
}