Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / Pithos.java @ b9a1049a

History | View | Annotate | Download (53.9 kB)

1
/*
2
 * Copyright 2011-2012 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.EntryPoint;
38
import com.google.gwt.core.client.GWT;
39
import com.google.gwt.core.client.JsArrayString;
40
import com.google.gwt.core.client.Scheduler;
41
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
42
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
43
import com.google.gwt.event.dom.client.ClickEvent;
44
import com.google.gwt.event.dom.client.ClickHandler;
45
import com.google.gwt.event.logical.shared.ResizeEvent;
46
import com.google.gwt.event.logical.shared.ResizeHandler;
47
import com.google.gwt.http.client.Request;
48
import com.google.gwt.http.client.Response;
49
import com.google.gwt.http.client.URL;
50
import com.google.gwt.i18n.client.DateTimeFormat;
51
import com.google.gwt.i18n.client.Dictionary;
52
import com.google.gwt.i18n.client.TimeZone;
53
import com.google.gwt.json.client.JSONObject;
54
import com.google.gwt.resources.client.ClientBundle;
55
import com.google.gwt.resources.client.CssResource;
56
import com.google.gwt.resources.client.ImageResource;
57
import com.google.gwt.resources.client.ImageResource.ImageOptions;
58
import com.google.gwt.user.client.*;
59
import com.google.gwt.user.client.ui.*;
60
import com.google.gwt.view.client.SelectionChangeEvent;
61
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
62
import com.google.gwt.view.client.SingleSelectionModel;
63
import gr.grnet.pithos.web.client.catalog.GetUserCatalogs;
64
import gr.grnet.pithos.web.client.catalog.UserCatalogs;
65
import gr.grnet.pithos.web.client.commands.UploadFileCommand;
66
import gr.grnet.pithos.web.client.foldertree.*;
67
import gr.grnet.pithos.web.client.grouptree.Group;
68
import gr.grnet.pithos.web.client.grouptree.GroupTreeView;
69
import gr.grnet.pithos.web.client.grouptree.GroupTreeViewModel;
70
import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView;
71
import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeViewModel;
72
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView;
73
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeViewModel;
74
import gr.grnet.pithos.web.client.rest.*;
75
import org.apache.http.HttpStatus;
76

    
77
import java.util.*;
78

    
79
/**
80
 * Entry point classes define <code>onModuleLoad()</code>.
81
 */
82
public class Pithos implements EntryPoint, ResizeHandler {
83

    
84
    public static final String HOME_CONTAINER = "pithos";
85

    
86
    public static final String TRASH_CONTAINER = "trash";
87

    
88
    public static final Configuration config = GWT.create(Configuration.class);
89

    
90
    public interface Style extends CssResource {
91
        String commandAnchor();
92

    
93
        String statistics();
94

    
95
        @ClassName("gwt-HTML")
96
        String html();
97

    
98
        String uploadAlert();
99

    
100
        String uploadAlertLink();
101

    
102
        String uploadAlertProgress();
103

    
104
        String uploadAlertPercent();
105

    
106
        String uploadAlertClose();
107
    }
108

    
109
    public interface Resources extends ClientBundle {
110
        @Source("Pithos.css")
111
        Style pithosCss();
112

    
113
        @Source("gr/grnet/pithos/resources/close-popup.png")
114
        ImageResource closePopup();
115
    }
116

    
117
    public static Resources resources = GWT.create(Resources.class);
118

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

    
125
    public String getUserID() {
126
        return userID;
127
    }
128

    
129
    public UserCatalogs getUserCatalogs() {
130
        return userCatalogs;
131
    }
132

    
133
    public String getCurrentUserDisplayNameOrID() {
134
        final String displayName = userCatalogs.getDisplayName(getUserID());
135
        return displayName == null ? getUserID() : displayName;
136
    }
137

    
138
    public boolean hasUserDisplayNameForID(String userID) {
139
        return userCatalogs.getDisplayName(userID) != null;
140
    }
141

    
142
    public String getUserDisplayNameForID(String userID) {
143
        return userCatalogs.getDisplayName(userID);
144
    }
145

    
146
    public String getUserIDForDisplayName(String displayName) {
147
        return userCatalogs.getUserID(displayName);
148
    }
149

    
150
    public List<String> getUserDisplayNamesForIDs(List<String> userIDs) {
151
        if(userIDs == null) {
152
            userIDs = new ArrayList<String>();
153
        }
154
        final List<String> userDisplayNames = new ArrayList<String>();
155
        for(String userID : userIDs) {
156
            final String displayName = getUserDisplayNameForID(userID);
157
            userDisplayNames.add(displayName);
158
        }
159

    
160
        return userDisplayNames;
161
    }
162

    
163
    public List<String> filterUserIDsWithUnknownDisplayName(Collection<String> userIDs) {
164
        if(userIDs == null) {
165
            userIDs = new ArrayList<String>();
166
        }
167
        final List<String> filtered = new ArrayList<String>();
168
        for(String userID : userIDs) {
169
            if(!this.userCatalogs.hasID(userID)) {
170
                filtered.add(userID);
171
            }
172
        }
173
        return filtered;
174
    }
175

    
176
    public void setAccount(AccountResource acct) {
177
        account = acct;
178
    }
179

    
180
    public AccountResource getAccount() {
181
        return account;
182
    }
183

    
184
    public void updateFolder(Folder f, boolean showfiles, Command callback, final boolean openParent) {
185
        folderTreeView.updateFolder(f, showfiles, callback, openParent);
186
    }
187

    
188
    public void updateGroupNode(Group group) {
189
        groupTreeView.updateGroupNode(group);
190
    }
191

    
192
    public void updateMySharedRoot() {
193
        mysharedTreeView.updateRoot();
194
    }
195

    
196
    public void updateSharedFolder(Folder f, boolean showfiles, Command callback) {
197
        mysharedTreeView.updateFolder(f, showfiles, callback);
198
    }
199

    
200
    public void updateSharedFolder(Folder f, boolean showfiles) {
201
        updateSharedFolder(f, showfiles, null);
202
    }
203

    
204
    public void updateOtherSharedFolder(Folder f, boolean showfiles, Command callback) {
205
        otherSharedTreeView.updateFolder(f, showfiles, callback);
206
    }
207

    
208
    public MysharedTreeView getMySharedTreeView() {
209
        return mysharedTreeView;
210
    }
211

    
212
    /**
213
     * An aggregate image bundle that pulls together all the images for this
214
     * application into a single bundle.
215
     */
216
    public interface Images extends TopPanel.Images, FileList.Images, ToolsMenu.Images {
217

    
218
        @Source("gr/grnet/pithos/resources/document.png")
219
        ImageResource folders();
220

    
221
        @Source("gr/grnet/pithos/resources/advancedsettings.png")
222
        @ImageOptions(width = 32, height = 32)
223
        ImageResource tools();
224
    }
225

    
226
    private Throwable error;
227

    
228
    /**
229
     * The Application Clipboard implementation;
230
     */
231
    private Clipboard clipboard = new Clipboard();
232

    
233
    /**
234
     * The top panel that contains the menu bar.
235
     */
236
    private TopPanel topPanel;
237

    
238
    /**
239
     * The panel that contains the various system messages.
240
     */
241
    private MessagePanel messagePanel = new MessagePanel(this, Pithos.images);
242

    
243
    /**
244
     * The bottom panel that contains the status bar.
245
     */
246
    StatusPanel statusPanel = null;
247

    
248
    /**
249
     * The file list widget.
250
     */
251
    private FileList fileList;
252

    
253
    /**
254
     * The tab panel that occupies the right side of the screen.
255
     */
256
    private VerticalPanel inner = new VerticalPanel();
257

    
258

    
259
    /**
260
     * The split panel that will contain the left and right panels.
261
     */
262
    private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
263

    
264
    /**
265
     * The currently selected item in the application, for use by the Edit menu
266
     * commands. Potential types are Folder, File, User and Group.
267
     */
268
    private Object currentSelection;
269

    
270
    public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
271

    
272
    /**
273
     * The ID that uniquely identifies the user in Pithos+.
274
     * Currently this is a UUID. It used to be the user's email.
275
     */
276
    private String userID = null;
277

    
278
    /**
279
     * Hold mappings from user UUIDs to emails and vice-versa.
280
     */
281
    private UserCatalogs userCatalogs = new UserCatalogs();
282

    
283
    /**
284
     * The authentication token of the current user.
285
     */
286
    private String userToken;
287

    
288
    VerticalPanel trees;
289

    
290
    SingleSelectionModel<Folder> folderTreeSelectionModel;
291
    FolderTreeViewModel folderTreeViewModel;
292
    FolderTreeView folderTreeView;
293

    
294
    SingleSelectionModel<Folder> mysharedTreeSelectionModel;
295
    MysharedTreeViewModel mysharedTreeViewModel;
296
    MysharedTreeView mysharedTreeView = null;
297

    
298
    protected SingleSelectionModel<Folder> otherSharedTreeSelectionModel;
299
    OtherSharedTreeViewModel otherSharedTreeViewModel;
300
    OtherSharedTreeView otherSharedTreeView = null;
301

    
302
    GroupTreeViewModel groupTreeViewModel;
303
    GroupTreeView groupTreeView;
304

    
305
    TreeView selectedTree;
306
    protected AccountResource account;
307

    
308
    Folder trash;
309

    
310
    List<Composite> treeViews = new ArrayList<Composite>();
311

    
312
    @SuppressWarnings("rawtypes")
313
    List<SingleSelectionModel> selectionModels = new ArrayList<SingleSelectionModel>();
314

    
315
    public Button upload;
316

    
317
    private HTML numOfFiles;
318

    
319
    private Toolbar toolbar;
320

    
321
    private FileUploadDialog fileUploadDialog = new FileUploadDialog(this);
322

    
323
    UploadAlert uploadAlert;
324

    
325
    Date lastModified;
326

    
327
    @Override
328
    public void onModuleLoad() {
329
        if(parseUserCredentials()) {
330
            initialize();
331
        }
332
    }
333

    
334
    private void initialize() {
335
        System.out.println("initialize(), userToken = " + userToken);
336
        lastModified = new Date(); //Initialize if-modified-since value with now.
337
        resources.pithosCss().ensureInjected();
338
        boolean bareContent = Window.Location.getParameter("noframe") != null;
339
        String contentWidth = bareContent ? "100%" : "75%";
340

    
341
        VerticalPanel outer = new VerticalPanel();
342
        outer.setWidth("100%");
343
        if(!bareContent) {
344
            outer.addStyleName("pithos-outer");
345
        }
346

    
347
        if(!bareContent) {
348
            topPanel = new TopPanel(this, Pithos.images);
349
            topPanel.setWidth("100%");
350
            outer.add(topPanel);
351
            outer.setCellHorizontalAlignment(topPanel, HasHorizontalAlignment.ALIGN_CENTER);
352
        }
353

    
354
        messagePanel.setVisible(false);
355
        outer.add(messagePanel);
356
        outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
357
        outer.setCellVerticalAlignment(messagePanel, HasVerticalAlignment.ALIGN_MIDDLE);
358

    
359
        HorizontalPanel header = new HorizontalPanel();
360
        header.addStyleName("pithos-header");
361
        header.setWidth(contentWidth);
362
        if(bareContent) {
363
            header.addStyleName("pithos-header-noframe");
364
        }
365
        upload = new Button("Upload", new ClickHandler() {
366
            @Override
367
            public void onClick(ClickEvent event) {
368
                if(getSelection() != null) {
369
                    new UploadFileCommand(Pithos.this, null, getSelection()).execute();
370
                }
371
            }
372
        });
373
        upload.addStyleName("pithos-uploadButton");
374
        header.add(upload);
375
        header.setCellHorizontalAlignment(upload, HasHorizontalAlignment.ALIGN_LEFT);
376
        header.setCellVerticalAlignment(upload, HasVerticalAlignment.ALIGN_MIDDLE);
377

    
378
        toolbar = new Toolbar(this);
379
        header.add(toolbar);
380
        header.setCellHorizontalAlignment(toolbar, HasHorizontalAlignment.ALIGN_CENTER);
381
        header.setCellVerticalAlignment(toolbar, HasVerticalAlignment.ALIGN_MIDDLE);
382

    
383
        HorizontalPanel folderStatistics = new HorizontalPanel();
384
        folderStatistics.addStyleName("pithos-folderStatistics");
385
        numOfFiles = new HTML();
386
        folderStatistics.add(numOfFiles);
387
        folderStatistics.setCellVerticalAlignment(numOfFiles, HasVerticalAlignment.ALIGN_MIDDLE);
388
        HTML numOfFilesLabel = new HTML("&nbsp;Files");
389
        folderStatistics.add(numOfFilesLabel);
390
        folderStatistics.setCellVerticalAlignment(numOfFilesLabel, HasVerticalAlignment.ALIGN_MIDDLE);
391
        header.add(folderStatistics);
392
        header.setCellHorizontalAlignment(folderStatistics, HasHorizontalAlignment.ALIGN_RIGHT);
393
        header.setCellVerticalAlignment(folderStatistics, HasVerticalAlignment.ALIGN_MIDDLE);
394
        header.setCellWidth(folderStatistics, "40px");
395
        outer.add(header);
396
        outer.setCellHorizontalAlignment(header, HasHorizontalAlignment.ALIGN_CENTER);
397
        // Inner contains the various lists
398
        inner.sinkEvents(Event.ONCONTEXTMENU);
399
        inner.setWidth("100%");
400

    
401
        folderTreeSelectionModel = new SingleSelectionModel<Folder>();
402
        folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
403
            @Override
404
            public void onSelectionChange(SelectionChangeEvent event) {
405
                if(folderTreeSelectionModel.getSelectedObject() != null) {
406
                    deselectOthers(folderTreeView, folderTreeSelectionModel);
407
                    applyPermissions(folderTreeSelectionModel.getSelectedObject());
408
                    Folder f = folderTreeSelectionModel.getSelectedObject();
409
                    updateFolder(f, true, new Command() {
410

    
411
                        @Override
412
                        public void execute() {
413
                            updateStatistics();
414
                        }
415
                    }, true);
416
                    showRelevantToolbarButtons();
417
                }
418
                else {
419
                    if(getSelectedTree().equals(folderTreeView)) {
420
                        setSelectedTree(null);
421
                    }
422
                    if(getSelectedTree() == null) {
423
                        showRelevantToolbarButtons();
424
                    }
425
                }
426
            }
427
        });
428
        selectionModels.add(folderTreeSelectionModel);
429

    
430
        folderTreeViewModel = new FolderTreeViewModel(this, folderTreeSelectionModel);
431
        folderTreeView = new FolderTreeView(folderTreeViewModel);
432
        treeViews.add(folderTreeView);
433

    
434
        fileList = new FileList(this, images);
435
        inner.add(fileList);
436

    
437
        trees = new VerticalPanel();
438
        trees.setWidth("100%");
439

    
440
        // Add the left and right panels to the split panel.
441
        splitPanel.setLeftWidget(trees);
442
        FlowPanel right = new FlowPanel();
443
        right.getElement().setId("rightPanel");
444
        right.add(inner);
445
        splitPanel.setRightWidget(right);
446
        splitPanel.setSplitPosition("219px");
447
        splitPanel.setSize("100%", "100%");
448
        splitPanel.addStyleName("pithos-splitPanel");
449
        splitPanel.setWidth(contentWidth);
450
        outer.add(splitPanel);
451
        outer.setCellHorizontalAlignment(splitPanel, HasHorizontalAlignment.ALIGN_CENTER);
452

    
453
        if(!bareContent) {
454
            statusPanel = new StatusPanel();
455
            statusPanel.setWidth("100%");
456
            outer.add(statusPanel);
457
            outer.setCellHorizontalAlignment(statusPanel, HasHorizontalAlignment.ALIGN_CENTER);
458
        }
459
        else {
460
            splitPanel.addStyleName("pithos-splitPanel-noframe");
461
        }
462

    
463
        // Hook the window resize event, so that we can adjust the UI.
464
        Window.addResizeHandler(this);
465
        // Clear out the window's built-in margin, because we want to take
466
        // advantage of the entire client area.
467
        Window.setMargin("0px");
468
        // Finally, add the outer panel to the RootPanel, so that it will be
469
        // displayed.
470
        RootPanel.get().add(outer);
471
        // Call the window resized handler to get the initial sizes setup. Doing
472
        // this in a deferred command causes it to occur after all widgets'
473
        // sizes have been computed by the browser.
474
        Scheduler.get().scheduleIncremental(new RepeatingCommand() {
475

    
476
            @Override
477
            public boolean execute() {
478
                if(!isCloudbarReady()) {
479
                    return true;
480
                }
481
                onWindowResized(Window.getClientHeight());
482
                return false;
483
            }
484
        });
485

    
486
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
487
            @Override
488
            public void execute() {
489
                fetchAccount(new Command() {
490

    
491
                    @Override
492
                    public void execute() {
493
                        if(!account.hasHomeContainer()) {
494
                            createHomeContainer(account, this);
495
                        }
496
                        else if(!account.hasTrashContainer()) {
497
                            createTrashContainer(this);
498
                        }
499
                        else {
500
                            for(Folder f : account.getContainers()) {
501
                                if(f.getName().equals(Pithos.TRASH_CONTAINER)) {
502
                                    trash = f;
503
                                    break;
504
                                }
505
                            }
506
                            trees.add(folderTreeView);
507
                            folderTreeViewModel.initialize(account, new Command() {
508

    
509
                                @Override
510
                                public void execute() {
511
                                    createMySharedTree();
512
                                }
513
                            });
514

    
515
                            HorizontalPanel separator = new HorizontalPanel();
516
                            separator.addStyleName("pithos-statisticsSeparator");
517
                            separator.add(new HTML(""));
518
                            trees.add(separator);
519

    
520
                            groupTreeViewModel = new GroupTreeViewModel(Pithos.this);
521
                            groupTreeView = new GroupTreeView(groupTreeViewModel);
522
                            treeViews.add(groupTreeView);
523
                            trees.add(groupTreeView);
524
                            folderTreeView.showStatistics(account);
525
                        }
526
                    }
527
                });
528
            }
529
        });
530
    }
531

    
532
    public void scheduleResfresh() {
533
        Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
534

    
535
            @Override
536
            public boolean execute() {
537
                final Folder f = getSelection();
538
                if(f == null) {
539
                    return true;
540
                }
541

    
542
                HeadRequest<Folder> head = new HeadRequest<Folder>(Folder.class, getApiPath(), f.getOwnerID(), "/" + f.getContainer()) {
543

    
544
                    @Override
545
                    public void onSuccess(Folder _result) {
546
                        lastModified = new Date();
547
                        if(getSelectedTree().equals(folderTreeView)) {
548
                            updateFolder(f, true, new Command() {
549

    
550
                                @Override
551
                                public void execute() {
552
                                    scheduleResfresh();
553
                                }
554

    
555
                            }, false);
556
                        }
557
                        else if(getSelectedTree().equals(mysharedTreeView)) {
558
                            updateSharedFolder(f, true, new Command() {
559

    
560
                                @Override
561
                                public void execute() {
562
                                    scheduleResfresh();
563
                                }
564
                            });
565
                        }
566
                        else {
567
                            scheduleResfresh();
568
                        }
569
                    }
570

    
571
                    @Override
572
                    public void onError(Throwable t) {
573
                        if(t instanceof RestException && ((RestException) t).getHttpStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
574
                            scheduleResfresh();
575
                        }
576
                        else if(retries >= MAX_RETRIES) {
577
                            GWT.log("Error heading folder", t);
578
                            setError(t);
579
                            if(t instanceof RestException) {
580
                                displayError("Error heading folder: " + ((RestException) t).getHttpStatusText());
581
                            }
582
                            else {
583
                                displayError("System error heading folder: " + t.getMessage());
584
                            }
585
                        }
586
                        else {//retry
587
                            GWT.log("Retry " + retries);
588
                            Scheduler.get().scheduleDeferred(this);
589
                        }
590
                    }
591

    
592
                    @Override
593
                    protected void onUnauthorized(Response response) {
594
                        if(retries >= MAX_RETRIES) {
595
                            sessionExpired();
596
                        }
597
                        else //retry
598
                        {
599
                            Scheduler.get().scheduleDeferred(this);
600
                        }
601
                    }
602
                };
603
                head.setHeader("X-Auth-Token", getUserToken());
604
                head.setHeader("If-Modified-Since", DateTimeFormat.getFormat("EEE, dd MMM yyyy HH:mm:ss").format(lastModified, TimeZone.createTimeZone(0)) + " GMT");
605
                Scheduler.get().scheduleDeferred(head);
606

    
607
                return false;
608
            }
609
        }, 3000);
610
    }
611

    
612
    public void applyPermissions(Folder f) {
613
        if(f != null) {
614
            if(f.isInTrash()) {
615
                upload.setEnabled(false);
616
                disableUploadArea();
617
            }
618
            else {
619
                Boolean[] perms = f.getPermissions().get(userID);
620
                if(f.getOwnerID().equals(userID) || (perms != null && perms[1] != null && perms[1])) {
621
                    upload.setEnabled(true);
622
                    enableUploadArea();
623
                }
624
                else {
625
                    upload.setEnabled(false);
626
                    disableUploadArea();
627
                }
628
            }
629
        }
630
        else {
631
            upload.setEnabled(false);
632
            disableUploadArea();
633
        }
634
    }
635

    
636
    @SuppressWarnings({"rawtypes", "unchecked"})
637
    public void deselectOthers(TreeView _selectedTree, SingleSelectionModel model) {
638
        selectedTree = _selectedTree;
639

    
640
        for(SingleSelectionModel s : selectionModels) {
641
            if(!s.equals(model) && s.getSelectedObject() != null) {
642
                s.setSelected(s.getSelectedObject(), false);
643
            }
644
        }
645
    }
646

    
647
    public void showFiles(final Folder f) {
648
        Set<File> files = f.getFiles();
649
        showFiles(files);
650
    }
651

    
652
    public void showFiles(Set<File> files) {
653
        fileList.setFiles(new ArrayList<File>(files));
654
    }
655

    
656
    /**
657
     * Parse and store the user credentials to the appropriate fields.
658
     */
659
    private boolean parseUserCredentials() {
660
        Configuration conf = (Configuration) GWT.create(Configuration.class);
661
        Dictionary otherProperties = Dictionary.getDictionary("otherProperties");
662
        System.out.println("otherProperties = " + otherProperties);
663
        String cookie = otherProperties.get("authCookie");
664
        System.out.println("cookie = " + cookie);
665
        Cookies.setCookie(cookie, "868fbb51-94a4-477d-8da3-dadad080c861|HlPjywM5FGAncsoNDzPZ2Q==");
666
//        Cookies.setCookie(cookie, "868fbb51-94a4-477d-8da3-dadad080c861%7CHlPjywM5FGAncsoNDzPZ2Q%3D%3D");
667
        for(String name: Cookies.getCookieNames()) {
668
            System.out.println("cookie name: " + name);
669
        }
670
        String auth = Cookies.getCookie(cookie);
671
        System.out.println("auth = " + auth);
672
        if(auth == null) {
673
            authenticateUser();
674
            return false;
675
        }
676
        if(auth.startsWith("\"")) {
677
            auth = auth.substring(1);
678
        }
679
        if(auth.endsWith("\"")) {
680
            auth = auth.substring(0, auth.length() - 1);
681
        }
682
        String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
683
        for(String authPart: authSplit) {
684
            System.out.println("authPart: " + authPart);
685
        }
686
        if(authSplit.length != 2) {
687
            authenticateUser();
688
            return false;
689
        }
690
        userID = authSplit[0];
691
        userToken = authSplit[1];
692
        System.out.println("userID = " + userID);
693
        System.out.println("userToken = " + userToken);
694

    
695
        String gotoUrl = Window.Location.getParameter("goto");
696
        if(gotoUrl != null && gotoUrl.length() > 0) {
697
            Window.Location.assign(gotoUrl);
698
            return false;
699
        }
700
        System.out.println("Returning true");
701
        return true;
702
    }
703

    
704
    /**
705
     * Redirect the user to the login page for authentication.
706
     */
707
    protected void authenticateUser() {
708
        Dictionary otherProperties = Dictionary.getDictionary("otherProperties");
709
        Window.Location.assign(otherProperties.get("loginUrl") + Window.Location.getHref());
710
    }
711

    
712
    public void fetchAccount(final Command callback) {
713
        System.out.println("fetchAccount(), userID = " + this.userID + ", userToken = " + this.userToken);
714
        String path = "?format=json";
715

    
716
        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, getApiPath(), userID, path) {
717
            @Override
718
            public void onSuccess(AccountResource _result) {
719
                System.out.println("fetchAccount(), userID = " + userID + ", userToken = " + userToken + " onSuccess()");
720
                account = _result;
721
                if(callback != null) {
722
                    callback.execute();
723
                }
724
                // Initialize the user catalog
725
                new GetUserCatalogs(Pithos.this, Pithos.this.getUserID()) {
726
                    @Override
727
                    public void onSuccess(Request request, Response response, JSONObject result, UserCatalogs usersCatalog) {
728
                        super.onSuccess(request, response, result, usersCatalog);
729
                        Pithos.this.userCatalogs.updateFrom(usersCatalog);
730
                    }
731
                }.scheduleDeferred();
732
            }
733

    
734
            @Override
735
            public void onError(Throwable t) {
736
                System.out.println("fetchAccount(), userID = " + userID + ", userToken = " + userToken + " onError() " + t.getClass().getName() + ": " + t.getMessage());
737
                GWT.log("Error getting account", t);
738
                setError(t);
739
                if(t instanceof RestException) {
740
                    System.out.println("fetchAccount(), userID = " + userID + ", userToken = " + userToken + " Error getting account: " + ((RestException) t).getHttpStatusText());
741
                    displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
742
                }
743
                else {
744
                    System.out.println("fetchAccount(), userID = " + userID + ", userToken = " + userToken + "System error fetching user data: " + t.getMessage());
745
                    displayError("System error fetching user data: " + t.getMessage());
746
                }
747
            }
748

    
749
            @Override
750
            protected void onUnauthorized(Response response) {
751
                System.out.println("fetchAccount(), userID = " + userID + ", userToken = " + userToken + " onUnauthorized()");
752
                sessionExpired();
753
            }
754
        };
755
        getAccount.setHeader("X-Auth-Token", userToken);
756
        Scheduler.get().scheduleDeferred(getAccount);
757
    }
758

    
759
    public void updateStatistics() {
760
        HeadRequest<AccountResource> headAccount = new HeadRequest<AccountResource>(AccountResource.class, getApiPath(), userID, "", account) {
761

    
762
            @Override
763
            public void onSuccess(AccountResource _result) {
764
                folderTreeView.showStatistics(account);
765
            }
766

    
767
            @Override
768
            public void onError(Throwable t) {
769
                GWT.log("Error getting account", t);
770
                setError(t);
771
                if(t instanceof RestException) {
772
                    displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
773
                }
774
                else {
775
                    displayError("System error fetching user data: " + t.getMessage());
776
                }
777
            }
778

    
779
            @Override
780
            protected void onUnauthorized(Response response) {
781
                sessionExpired();
782
            }
783
        };
784
        headAccount.setHeader("X-Auth-Token", userToken);
785
        Scheduler.get().scheduleDeferred(headAccount);
786
    }
787

    
788
    protected void createHomeContainer(final AccountResource _account, final Command callback) {
789
        String path = "/" + Pithos.HOME_CONTAINER;
790
        PutRequest createPithos = new PutRequest(getApiPath(), getUserID(), path) {
791
            @Override
792
            public void onSuccess(Resource result) {
793
                if(!_account.hasTrashContainer()) {
794
                    createTrashContainer(callback);
795
                }
796
                else {
797
                    fetchAccount(callback);
798
                }
799
            }
800

    
801
            @Override
802
            public void onError(Throwable t) {
803
                GWT.log("Error creating pithos", t);
804
                setError(t);
805
                if(t instanceof RestException) {
806
                    displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
807
                }
808
                else {
809
                    displayError("System error Error creating pithos: " + t.getMessage());
810
                }
811
            }
812

    
813
            @Override
814
            protected void onUnauthorized(Response response) {
815
                sessionExpired();
816
            }
817
        };
818
        createPithos.setHeader("X-Auth-Token", getUserToken());
819
        Scheduler.get().scheduleDeferred(createPithos);
820
    }
821

    
822
    protected void createTrashContainer(final Command callback) {
823
        String path = "/" + Pithos.TRASH_CONTAINER;
824
        PutRequest createPithos = new PutRequest(getApiPath(), getUserID(), path) {
825
            @Override
826
            public void onSuccess(Resource result) {
827
                fetchAccount(callback);
828
            }
829

    
830
            @Override
831
            public void onError(Throwable t) {
832
                GWT.log("Error creating pithos", t);
833
                setError(t);
834
                if(t instanceof RestException) {
835
                    displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
836
                }
837
                else {
838
                    displayError("System error Error creating pithos: " + t.getMessage());
839
                }
840
            }
841

    
842
            @Override
843
            protected void onUnauthorized(Response response) {
844
                sessionExpired();
845
            }
846
        };
847
        createPithos.setHeader("X-Auth-Token", getUserToken());
848
        Scheduler.get().scheduleDeferred(createPithos);
849
    }
850

    
851
    /**
852
     * Creates an HTML fragment that places an image & caption together, for use
853
     * in a group header.
854
     *
855
     * @param imageProto an image prototype for an image
856
     * @param caption    the group caption
857
     * @return the header HTML fragment
858
     */
859
    private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
860
        String captionHTML = "<table class='caption' cellpadding='0' "
861
            + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML()
862
            + "</td><td id =" + caption + " class='rcaption'><b style='white-space:nowrap'>&nbsp;"
863
            + caption + "</b></td></tr></table>";
864
        return captionHTML;
865
    }
866

    
867
    protected void onWindowResized(int height) {
868
        // Adjust the split panel to take up the available room in the window.
869
        int newHeight = height - splitPanel.getAbsoluteTop() - 153;
870
        if(newHeight < 1) {
871
            newHeight = 1;
872
        }
873
        splitPanel.setHeight("" + newHeight);
874
        inner.setHeight("" + newHeight);
875
    }
876

    
877
    native boolean isCloudbarReady()/*-{
878
      if ($wnd.$("div.cloudbar") && $wnd.$("div.cloudbar").height() > 0)
879
        return true;
880
      return false;
881
    }-*/;
882

    
883
    @Override
884
    public void onResize(ResizeEvent event) {
885
        int height = event.getHeight();
886
        onWindowResized(height);
887
    }
888

    
889
    /**
890
     * Display an error message.
891
     *
892
     * @param msg the message to display
893
     */
894
    public void displayError(String msg) {
895
        messagePanel.displayError(msg);
896
        onWindowResized(Window.getClientHeight());
897
    }
898

    
899
    /**
900
     * Display a warning message.
901
     *
902
     * @param msg the message to display
903
     */
904
    public void displayWarning(String msg) {
905
        messagePanel.displayWarning(msg);
906
        onWindowResized(Window.getClientHeight());
907
    }
908

    
909
    /**
910
     * Display an informational message.
911
     *
912
     * @param msg the message to display
913
     */
914
    public void displayInformation(String msg) {
915
        messagePanel.displayInformation(msg);
916
        onWindowResized(Window.getClientHeight());
917
    }
918

    
919
    /**
920
     * Retrieve the fileList.
921
     *
922
     * @return the fileList
923
     */
924
    public FileList getFileList() {
925
        return fileList;
926
    }
927

    
928
    /**
929
     * Retrieve the topPanel.
930
     *
931
     * @return the topPanel
932
     */
933
    TopPanel getTopPanel() {
934
        return topPanel;
935
    }
936

    
937
    /**
938
     * Retrieve the clipboard.
939
     *
940
     * @return the clipboard
941
     */
942
    public Clipboard getClipboard() {
943
        return clipboard;
944
    }
945

    
946
    public StatusPanel getStatusPanel() {
947
        return statusPanel;
948
    }
949

    
950
    public String getUserToken() {
951
        return userToken;
952
    }
953

    
954
    public static native void preventIESelection() /*-{
955
      $doc.body.onselectstart = function () {
956
        return false;
957
      };
958
    }-*/;
959

    
960
    public static native void enableIESelection() /*-{
961
      if ($doc.body.onselectstart != null)
962
        $doc.body.onselectstart = null;
963
    }-*/;
964

    
965
    /**
966
     * @return the absolute path of the API root URL
967
     */
968
    public String getApiPath() {
969
        Configuration conf = (Configuration) GWT.create(Configuration.class);
970
        return conf.apiPath();
971
    }
972

    
973
    /**
974
     * History support for folder navigation
975
     * adds a new browser history entry
976
     *
977
     * @param key
978
     */
979
    public void updateHistory(String key) {
980
//                Replace any whitespace of the initial string to "+"
981
//                String result = key.replaceAll("\\s","+");
982
//                Add a new browser history entry.
983
//                History.newItem(result);
984
        History.newItem(key);
985
    }
986

    
987
    public void deleteFolder(final Folder folder, final Command callback) {
988
        final PleaseWaitPopup pwp = new PleaseWaitPopup();
989
        pwp.center();
990
        String path = "/" + folder.getContainer() + "/" + folder.getPrefix() + "?delimiter=/" + "&t=" + System.currentTimeMillis();
991
        DeleteRequest deleteFolder = new DeleteRequest(getApiPath(), folder.getOwnerID(), path) {
992

    
993
            @Override
994
            protected void onUnauthorized(Response response) {
995
                pwp.hide();
996
                sessionExpired();
997
            }
998

    
999
            @Override
1000
            public void onSuccess(Resource result) {
1001
                updateFolder(folder.getParent(), true, new Command() {
1002

    
1003
                    @Override
1004
                    public void execute() {
1005
                        folderTreeSelectionModel.setSelected(folder.getParent(), true);
1006
                        updateStatistics();
1007
                        if(callback != null) {
1008
                            callback.execute();
1009
                        }
1010
                        pwp.hide();
1011
                    }
1012
                }, true);
1013
            }
1014

    
1015
            @Override
1016
            public void onError(Throwable t) {
1017
                GWT.log("", t);
1018
                setError(t);
1019
                if(t instanceof RestException) {
1020
                    if(((RestException) t).getHttpStatusCode() != Response.SC_NOT_FOUND) {
1021
                        displayError("Unable to delete folder: " + ((RestException) t).getHttpStatusText());
1022
                    }
1023
                    else {
1024
                        onSuccess(null);
1025
                    }
1026
                }
1027
                else {
1028
                    displayError("System error unable to delete folder: " + t.getMessage());
1029
                }
1030
                pwp.hide();
1031
            }
1032
        };
1033
        deleteFolder.setHeader("X-Auth-Token", getUserToken());
1034
        Scheduler.get().scheduleDeferred(deleteFolder);
1035
    }
1036

    
1037
    public FolderTreeView getFolderTreeView() {
1038
        return folderTreeView;
1039
    }
1040

    
1041
    public void copyFiles(final Iterator<File> iter, final String targetUsername, final String targetUri, final Command callback) {
1042
        if(iter.hasNext()) {
1043
            File file = iter.next();
1044
            String path = targetUri + "/" + file.getName();
1045
            PutRequest copyFile = new PutRequest(getApiPath(), targetUsername, path) {
1046
                @Override
1047
                public void onSuccess(Resource result) {
1048
                    copyFiles(iter, targetUsername, targetUri, callback);
1049
                }
1050

    
1051
                @Override
1052
                public void onError(Throwable t) {
1053
                    GWT.log("", t);
1054
                    setError(t);
1055
                    if(t instanceof RestException) {
1056
                        displayError("Unable to copy file: " + ((RestException) t).getHttpStatusText());
1057
                    }
1058
                    else {
1059
                        displayError("System error unable to copy file: " + t.getMessage());
1060
                    }
1061
                }
1062

    
1063
                @Override
1064
                protected void onUnauthorized(Response response) {
1065
                    sessionExpired();
1066
                }
1067
            };
1068
            copyFile.setHeader("X-Auth-Token", getUserToken());
1069
            copyFile.setHeader("X-Copy-From", URL.encodePathSegment(file.getUri()));
1070
            if(!file.getOwnerID().equals(targetUsername)) {
1071
                copyFile.setHeader("X-Source-Account", URL.encodePathSegment(file.getOwnerID()));
1072
            }
1073
            copyFile.setHeader("Content-Type", file.getContentType());
1074
            Scheduler.get().scheduleDeferred(copyFile);
1075
        }
1076
        else if(callback != null) {
1077
            callback.execute();
1078
        }
1079
    }
1080

    
1081
    public void copyFolder(final Folder f, final String targetUsername, final String targetUri, boolean move, final Command callback) {
1082
        String path = targetUri + "?delimiter=/";
1083
        PutRequest copyFolder = new PutRequest(getApiPath(), targetUsername, path) {
1084
            @Override
1085
            public void onSuccess(Resource result) {
1086
                if(callback != null) {
1087
                    callback.execute();
1088
                }
1089
            }
1090

    
1091
            @Override
1092
            public void onError(Throwable t) {
1093
                GWT.log("", t);
1094
                setError(t);
1095
                if(t instanceof RestException) {
1096
                    displayError("Unable to copy folder: " + ((RestException) t).getHttpStatusText());
1097
                }
1098
                else {
1099
                    displayError("System error copying folder: " + t.getMessage());
1100
                }
1101
            }
1102

    
1103
            @Override
1104
            protected void onUnauthorized(Response response) {
1105
                sessionExpired();
1106
            }
1107
        };
1108
        copyFolder.setHeader("X-Auth-Token", getUserToken());
1109
        copyFolder.setHeader("Accept", "*/*");
1110
        copyFolder.setHeader("Content-Length", "0");
1111
        copyFolder.setHeader("Content-Type", "application/directory");
1112
        if(!f.getOwnerID().equals(targetUsername)) {
1113
            copyFolder.setHeader("X-Source-Account", f.getOwnerID());
1114
        }
1115
        if(move) {
1116
            copyFolder.setHeader("X-Move-From", URL.encodePathSegment(f.getUri()));
1117
        }
1118
        else {
1119
            copyFolder.setHeader("X-Copy-From", URL.encodePathSegment(f.getUri()));
1120
        }
1121
        Scheduler.get().scheduleDeferred(copyFolder);
1122
    }
1123

    
1124
    public void addSelectionModel(@SuppressWarnings("rawtypes") SingleSelectionModel model) {
1125
        selectionModels.add(model);
1126
    }
1127

    
1128
    public OtherSharedTreeView getOtherSharedTreeView() {
1129
        return otherSharedTreeView;
1130
    }
1131

    
1132
    public void updateTrash(boolean showFiles, Command callback) {
1133
        updateFolder(trash, showFiles, callback, true);
1134
    }
1135

    
1136
    public void updateGroupsNode() {
1137
        groupTreeView.updateGroupNode(null);
1138
    }
1139

    
1140
    public Group addGroup(String groupname) {
1141
        Group newGroup = new Group(groupname);
1142
        account.addGroup(newGroup);
1143
        groupTreeView.updateGroupNode(null);
1144
        return newGroup;
1145
    }
1146

    
1147
    public void removeGroup(Group group) {
1148
        account.removeGroup(group);
1149
        updateGroupsNode();
1150
    }
1151

    
1152
    public TreeView getSelectedTree() {
1153
        return selectedTree;
1154
    }
1155

    
1156
    public void setSelectedTree(TreeView selected) {
1157
        selectedTree = selected;
1158
    }
1159

    
1160
    public Folder getSelection() {
1161
        if(selectedTree != null) {
1162
            return selectedTree.getSelection();
1163
        }
1164
        return null;
1165
    }
1166

    
1167
    public void showFolderStatistics(int folderFileCount) {
1168
        numOfFiles.setHTML(String.valueOf(folderFileCount));
1169
    }
1170

    
1171
    public GroupTreeView getGroupTreeView() {
1172
        return groupTreeView;
1173
    }
1174

    
1175
    public void sessionExpired() {
1176
        new SessionExpiredDialog(this).center();
1177
    }
1178

    
1179
    public void updateRootFolder(Command callback) {
1180
        updateFolder(account.getPithos(), false, callback, true);
1181
    }
1182

    
1183
    void createMySharedTree() {
1184
        mysharedTreeSelectionModel = new SingleSelectionModel<Folder>();
1185
        mysharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
1186
            @Override
1187
            public void onSelectionChange(SelectionChangeEvent event) {
1188
                if(mysharedTreeSelectionModel.getSelectedObject() != null) {
1189
                    deselectOthers(mysharedTreeView, mysharedTreeSelectionModel);
1190
                    upload.setEnabled(false);
1191
                    disableUploadArea();
1192
                    updateSharedFolder(mysharedTreeSelectionModel.getSelectedObject(), true);
1193
                    showRelevantToolbarButtons();
1194
                }
1195
                else {
1196
                    if(getSelectedTree().equals(mysharedTreeView)) {
1197
                        setSelectedTree(null);
1198
                    }
1199
                    if(getSelectedTree() == null) {
1200
                        showRelevantToolbarButtons();
1201
                    }
1202
                }
1203
            }
1204
        });
1205
        selectionModels.add(mysharedTreeSelectionModel);
1206
        mysharedTreeViewModel = new MysharedTreeViewModel(Pithos.this, mysharedTreeSelectionModel);
1207
        mysharedTreeViewModel.initialize(new Command() {
1208

    
1209
            @Override
1210
            public void execute() {
1211
                mysharedTreeView = new MysharedTreeView(mysharedTreeViewModel);
1212
                trees.insert(mysharedTreeView, 2);
1213
                treeViews.add(mysharedTreeView);
1214
                createOtherSharedTree();
1215
            }
1216
        });
1217
    }
1218

    
1219
    void createOtherSharedTree() {
1220
        otherSharedTreeSelectionModel = new SingleSelectionModel<Folder>();
1221
        otherSharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
1222
            @Override
1223
            public void onSelectionChange(SelectionChangeEvent event) {
1224
                if(otherSharedTreeSelectionModel.getSelectedObject() != null) {
1225
                    deselectOthers(otherSharedTreeView, otherSharedTreeSelectionModel);
1226
                    applyPermissions(otherSharedTreeSelectionModel.getSelectedObject());
1227
                    updateOtherSharedFolder(otherSharedTreeSelectionModel.getSelectedObject(), true, null);
1228
                    showRelevantToolbarButtons();
1229
                }
1230
                else {
1231
                    if(getSelectedTree().equals(otherSharedTreeView)) {
1232
                        setSelectedTree(null);
1233
                    }
1234
                    if(getSelectedTree() == null) {
1235
                        showRelevantToolbarButtons();
1236
                    }
1237
                }
1238
            }
1239
        });
1240
        selectionModels.add(otherSharedTreeSelectionModel);
1241
        otherSharedTreeViewModel = new OtherSharedTreeViewModel(Pithos.this, otherSharedTreeSelectionModel);
1242
        otherSharedTreeViewModel.initialize(new Command() {
1243

    
1244
            @Override
1245
            public void execute() {
1246
                otherSharedTreeView = new OtherSharedTreeView(otherSharedTreeViewModel);
1247
                trees.insert(otherSharedTreeView, 1);
1248
                treeViews.add(otherSharedTreeView);
1249
                scheduleResfresh();
1250
            }
1251
        });
1252
    }
1253

    
1254
    public native void log1(String message)/*-{
1255
      $wnd.console.log(message);
1256
    }-*/;
1257

    
1258
    public String getErrorData() {
1259
        if(error != null) {
1260
            return error.toString();
1261
        }
1262
        return "";
1263
    }
1264

    
1265
    public void setError(Throwable t) {
1266
        error = t;
1267
    }
1268

    
1269
    public void showRelevantToolbarButtons() {
1270
        toolbar.showRelevantButtons();
1271
    }
1272

    
1273
    public FileUploadDialog getFileUploadDialog() {
1274
        if(fileUploadDialog == null) {
1275
            fileUploadDialog = new FileUploadDialog(this);
1276
        }
1277
        return fileUploadDialog;
1278
    }
1279

    
1280
    public void hideUploadIndicator() {
1281
        upload.removeStyleName("pithos-uploadButton-loading");
1282
        upload.setTitle("");
1283
    }
1284

    
1285
    public void showUploadIndicator() {
1286
        upload.addStyleName("pithos-uploadButton-loading");
1287
        upload.setTitle("Upload in progress. Click for details.");
1288
    }
1289

    
1290
    public void scheduleFolderHeadCommand(final Folder folder, final Command callback) {
1291
        if(folder == null) {
1292
            if(callback != null) {
1293
                callback.execute();
1294
            }
1295
        }
1296
        else {
1297
            HeadRequest<Folder> headFolder = new HeadRequest<Folder>(Folder.class, getApiPath(), folder.getOwnerID(), folder.getUri(), folder) {
1298

    
1299
                @Override
1300
                public void onSuccess(Folder _result) {
1301
                    if(callback != null) {
1302
                        callback.execute();
1303
                    }
1304
                }
1305

    
1306
                @Override
1307
                public void onError(Throwable t) {
1308
                    if(t instanceof RestException) {
1309
                        if(((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) {
1310
                            final String path = folder.getUri();
1311
                            PutRequest newFolder = new PutRequest(getApiPath(), folder.getOwnerID(), path) {
1312
                                @Override
1313
                                public void onSuccess(Resource _result) {
1314
                                    scheduleFolderHeadCommand(folder, callback);
1315
                                }
1316

    
1317
                                @Override
1318
                                public void onError(Throwable _t) {
1319
                                    GWT.log("", _t);
1320
                                    setError(_t);
1321
                                    if(_t instanceof RestException) {
1322
                                        displayError("Unable to create folder: " + ((RestException) _t).getHttpStatusText());
1323
                                    }
1324
                                    else {
1325
                                        displayError("System error creating folder: " + _t.getMessage());
1326
                                    }
1327
                                }
1328

    
1329
                                @Override
1330
                                protected void onUnauthorized(Response response) {
1331
                                    sessionExpired();
1332
                                }
1333
                            };
1334
                            newFolder.setHeader("X-Auth-Token", getUserToken());
1335
                            newFolder.setHeader("Content-Type", "application/folder");
1336
                            newFolder.setHeader("Accept", "*/*");
1337
                            newFolder.setHeader("Content-Length", "0");
1338
                            Scheduler.get().scheduleDeferred(newFolder);
1339
                        }
1340
                        else if(((RestException) t).getHttpStatusCode() == Response.SC_FORBIDDEN) {
1341
                            onSuccess(folder);
1342
                        }
1343
                        else {
1344
                            displayError("Error heading folder: " + ((RestException) t).getHttpStatusText());
1345
                        }
1346
                    }
1347
                    else {
1348
                        displayError("System error heading folder: " + t.getMessage());
1349
                    }
1350

    
1351
                    GWT.log("Error heading folder", t);
1352
                    setError(t);
1353
                }
1354

    
1355
                @Override
1356
                protected void onUnauthorized(Response response) {
1357
                    sessionExpired();
1358
                }
1359
            };
1360
            headFolder.setHeader("X-Auth-Token", getUserToken());
1361
            Scheduler.get().scheduleDeferred(headFolder);
1362
        }
1363
    }
1364

    
1365
    public void scheduleFileHeadCommand(File f, final Command callback) {
1366
        HeadRequest<File> headFile = new HeadRequest<File>(File.class, getApiPath(), f.getOwnerID(), f.getUri(), f) {
1367

    
1368
            @Override
1369
            public void onSuccess(File _result) {
1370
                if(callback != null) {
1371
                    callback.execute();
1372
                }
1373
            }
1374

    
1375
            @Override
1376
            public void onError(Throwable t) {
1377
                GWT.log("Error heading file", t);
1378
                setError(t);
1379
                if(t instanceof RestException) {
1380
                    displayError("Error heading file: " + ((RestException) t).getHttpStatusText());
1381
                }
1382
                else {
1383
                    displayError("System error heading file: " + t.getMessage());
1384
                }
1385
            }
1386

    
1387
            @Override
1388
            protected void onUnauthorized(Response response) {
1389
                sessionExpired();
1390
            }
1391
        };
1392
        headFile.setHeader("X-Auth-Token", getUserToken());
1393
        Scheduler.get().scheduleDeferred(headFile);
1394
    }
1395

    
1396
    public boolean isMySharedSelected() {
1397
        return getSelectedTree().equals(getMySharedTreeView());
1398
    }
1399

    
1400
    private Folder getUploadFolder() {
1401
        if(folderTreeView.equals(getSelectedTree()) || otherSharedTreeView.equals(getSelectedTree())) {
1402
            return getSelection();
1403
        }
1404
        return null;
1405
    }
1406

    
1407
    private void updateUploadFolder() {
1408
        updateUploadFolder(null);
1409
    }
1410

    
1411
    private void updateUploadFolder(final JsArrayString urls) {
1412
        if(folderTreeView.equals(getSelectedTree()) || otherSharedTreeView.equals(getSelectedTree())) {
1413
            Folder f = getSelection();
1414
            if(getSelectedTree().equals(getFolderTreeView())) {
1415
                updateFolder(f, true, new Command() {
1416

    
1417
                    @Override
1418
                    public void execute() {
1419
                        updateStatistics();
1420
                        if(urls != null) {
1421
                            selectUploadedFiles(urls);
1422
                        }
1423
                    }
1424
                }, false);
1425
            }
1426
            else {
1427
                updateOtherSharedFolder(f, true, null);
1428
            }
1429
        }
1430
    }
1431

    
1432
    public native void disableUploadArea() /*-{
1433
      var uploader = $wnd.$("#uploader").pluploadQueue();
1434
      var dropElm = $wnd.document.getElementById('rightPanel');
1435
      $wnd.plupload.removeAllEvents(dropElm, uploader.id);
1436
    }-*/;
1437

    
1438
    public native void enableUploadArea() /*-{
1439
      var uploader = $wnd.$("#uploader").pluploadQueue();
1440
      var dropElm = $wnd.document.getElementById('rightPanel');
1441
      $wnd.plupload.removeAllEvents(dropElm, uploader.id);
1442
      if (uploader.runtime == 'html5') {
1443
        uploader.settings.drop_element = 'rightPanel';
1444
        uploader.trigger('PostInit');
1445
      }
1446
    }-*/;
1447

    
1448
    public void showUploadAlert(int nOfFiles) {
1449
        if(uploadAlert == null) {
1450
            uploadAlert = new UploadAlert(this, nOfFiles);
1451
        }
1452
        if(!uploadAlert.isShowing()) {
1453
            uploadAlert.setPopupPositionAndShow(new PopupPanel.PositionCallback() {
1454

    
1455
                @Override
1456
                public void setPosition(int offsetWidth, int offsetHeight) {
1457
                    uploadAlert.setPopupPosition((Window.getClientWidth() - offsetWidth) / 2, statusPanel.getAbsoluteTop() - offsetHeight);
1458
                }
1459
            });
1460
        }
1461
        uploadAlert.setNumOfFiles(nOfFiles);
1462
    }
1463

    
1464
    public void hideUploadAlert() {
1465
        if(uploadAlert != null && uploadAlert.isShowing()) {
1466
            uploadAlert.hide();
1467
        }
1468
    }
1469

    
1470
    public void selectUploadedFiles(JsArrayString urls) {
1471
        List<String> selectedUrls = new ArrayList<String>();
1472
        for(int i = 0; i < urls.length(); i++) {
1473
            selectedUrls.add(urls.get(i));
1474
        }
1475
        fileList.selectByUrl(selectedUrls);
1476
    }
1477

    
1478
    public void emptyContainer(final Folder container) {
1479
        String path = "/" + container.getName() + "?delimiter=/";
1480
        DeleteRequest delete = new DeleteRequest(getApiPath(), getUserID(), path) {
1481

    
1482
            @Override
1483
            protected void onUnauthorized(Response response) {
1484
                sessionExpired();
1485
            }
1486

    
1487
            @Override
1488
            public void onSuccess(Resource result) {
1489
                updateFolder(container, true, null, true);
1490
            }
1491

    
1492
            @Override
1493
            public void onError(Throwable t) {
1494
                GWT.log("Error deleting trash", t);
1495
                setError(t);
1496
                if(t instanceof RestException) {
1497
                    displayError("Error deleting trash: " + ((RestException) t).getHttpStatusText());
1498
                }
1499
                else {
1500
                    displayError("System error deleting trash: " + t.getMessage());
1501
                }
1502
            }
1503
        };
1504
        delete.setHeader("X-Auth-Token", getUserToken());
1505
        Scheduler.get().scheduleDeferred(delete);
1506
    }
1507
}