Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (45.1 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 gr.grnet.pithos.web.client.commands.NewFolderCommand;
38
import gr.grnet.pithos.web.client.commands.UploadFileCommand;
39
import gr.grnet.pithos.web.client.foldertree.AccountResource;
40
import gr.grnet.pithos.web.client.foldertree.File;
41
import gr.grnet.pithos.web.client.foldertree.Folder;
42
import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
43
import gr.grnet.pithos.web.client.foldertree.FolderTreeViewModel;
44
import gr.grnet.pithos.web.client.foldertree.Resource;
45
import gr.grnet.pithos.web.client.grouptree.Group;
46
import gr.grnet.pithos.web.client.grouptree.GroupTreeView;
47
import gr.grnet.pithos.web.client.grouptree.GroupTreeViewModel;
48
import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView;
49
import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeViewModel;
50
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView;
51
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeViewModel;
52
import gr.grnet.pithos.web.client.rest.DeleteRequest;
53
import gr.grnet.pithos.web.client.rest.GetRequest;
54
import gr.grnet.pithos.web.client.rest.HeadRequest;
55
import gr.grnet.pithos.web.client.rest.PutRequest;
56
import gr.grnet.pithos.web.client.rest.RestException;
57
import gr.grnet.pithos.web.client.tagtree.Tag;
58
import gr.grnet.pithos.web.client.tagtree.TagTreeView;
59
import gr.grnet.pithos.web.client.tagtree.TagTreeViewModel;
60

    
61
import java.util.ArrayList;
62
import java.util.Date;
63
import java.util.HashMap;
64
import java.util.Iterator;
65
import java.util.List;
66
import java.util.Set;
67

    
68
import com.google.gwt.core.client.EntryPoint;
69
import com.google.gwt.core.client.GWT;
70
import com.google.gwt.core.client.Scheduler;
71
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
72
import com.google.gwt.dom.client.Style.Display;
73
import com.google.gwt.event.dom.client.ClickEvent;
74
import com.google.gwt.event.dom.client.ClickHandler;
75
import com.google.gwt.event.logical.shared.ResizeEvent;
76
import com.google.gwt.event.logical.shared.ResizeHandler;
77
import com.google.gwt.http.client.Request;
78
import com.google.gwt.http.client.RequestBuilder;
79
import com.google.gwt.http.client.RequestCallback;
80
import com.google.gwt.http.client.RequestException;
81
import com.google.gwt.http.client.Response;
82
import com.google.gwt.http.client.URL;
83
import com.google.gwt.i18n.client.NumberFormat;
84
import com.google.gwt.json.client.JSONArray;
85
import com.google.gwt.json.client.JSONObject;
86
import com.google.gwt.json.client.JSONParser;
87
import com.google.gwt.json.client.JSONString;
88
import com.google.gwt.json.client.JSONValue;
89
import com.google.gwt.resources.client.ImageResource;
90
import com.google.gwt.resources.client.ImageResource.ImageOptions;
91
import com.google.gwt.user.client.Command;
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.Anchor;
98
import com.google.gwt.user.client.ui.Button;
99
import com.google.gwt.user.client.ui.Composite;
100
import com.google.gwt.user.client.ui.FlowPanel;
101
import com.google.gwt.user.client.ui.HTML;
102
import com.google.gwt.user.client.ui.HTMLPanel;
103
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
104
import com.google.gwt.user.client.ui.HasVerticalAlignment;
105
import com.google.gwt.user.client.ui.HorizontalPanel;
106
import com.google.gwt.user.client.ui.HorizontalSplitPanel;
107
import com.google.gwt.user.client.ui.Image;
108
import com.google.gwt.user.client.ui.RootPanel;
109
import com.google.gwt.user.client.ui.VerticalPanel;
110
import com.google.gwt.view.client.SelectionChangeEvent;
111
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
112
import com.google.gwt.view.client.SingleSelectionModel;
113

    
114
/**
115
 * Entry point classes define <code>onModuleLoad()</code>.
116
 */
117
public class Pithos implements EntryPoint, ResizeHandler {
118

    
119
        public static final String HOME_CONTAINER = "pithos";
120

    
121
        public static final String TRASH_CONTAINER = "trash";
122
        
123
        /**
124
         * Instantiate an application-level image bundle. This object will provide
125
         * programmatic access to all the images needed by widgets.
126
         */
127
        static Images images = (Images) GWT.create(Images.class);
128

    
129
    public String getUsername() {
130
        return username;
131
    }
132

    
133
    public void setAccount(AccountResource acct) {
134
        account = acct;
135
    }
136

    
137
    public AccountResource getAccount() {
138
        return account;
139
    }
140

    
141
    public void updateFolder(Folder f, boolean showfiles, Command callback) {
142
        folderTreeView.updateFolder(f, showfiles, callback);
143
    }
144

    
145
    public void updateGroupNode(Group group) {
146
        groupTreeView.updateGroupNode(group);
147
    }
148

    
149
    public void updateMySharedRoot() {
150
            mysharedTreeView.updateRoot();
151
    }
152
    
153
    public void updateSharedFolder(Folder f, boolean showfiles) {
154
            mysharedTreeView.updateFolder(f, showfiles);
155
    }
156
    
157
    public void updateOtherSharedFolder(Folder f, boolean showfiles) {
158
            otherSharedTreeView.updateFolder(f, showfiles);
159
    }
160

    
161
    public List<Tag> getAllTags() {
162
        List<Tag> tagList = new ArrayList<Tag>();
163
        for (Folder f : account.getContainers()) {
164
            for (String t : f.getTags()) {
165
                tagList.add(new Tag(t));
166
            }
167
        }
168
        return tagList;
169
    }
170

    
171
    public MysharedTreeView getMySharedTreeView() {
172
        return mysharedTreeView;
173
    }
174

    
175
    /**
176
         * An aggregate image bundle that pulls together all the images for this
177
         * application into a single bundle.
178
         */
179
        public interface Images extends TopPanel.Images, FileList.Images, ToolsMenu.Images {
180

    
181
                @Source("gr/grnet/pithos/resources/document.png")
182
                ImageResource folders();
183

    
184
                @Source("gr/grnet/pithos/resources/advancedsettings.png")
185
                @ImageOptions(width=32, height=32)
186
                ImageResource tools();
187
        }
188

    
189
        private Throwable error;
190
        
191
        /**
192
         * The Application Clipboard implementation;
193
         */
194
        private Clipboard clipboard = new Clipboard();
195

    
196
        /**
197
         * The top panel that contains the menu bar.
198
         */
199
        private TopPanel topPanel;
200

    
201
        /**
202
         * The panel that contains the various system messages.
203
         */
204
        private MessagePanel messagePanel = new MessagePanel(this, Pithos.images);
205

    
206
        /**
207
         * The bottom panel that contains the status bar.
208
         */
209
        private StatusPanel statusPanel = null;
210

    
211
        /**
212
         * The file list widget.
213
         */
214
        private FileList fileList;
215

    
216
        /**
217
         * The tab panel that occupies the right side of the screen.
218
         */
219
        private VerticalPanel inner = new VerticalPanel();
220

    
221

    
222
        /**
223
         * The split panel that will contain the left and right panels.
224
         */
225
        private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
226

    
227
        /**
228
         * The currently selected item in the application, for use by the Edit menu
229
         * commands. Potential types are Folder, File, User and Group.
230
         */
231
        private Object currentSelection;
232

    
233
        public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
234

    
235
    private String username = null;
236

    
237
    /**
238
     * The authentication token of the current user.
239
     */
240
    private String token;
241

    
242
    VerticalPanel trees;
243
    
244
    SingleSelectionModel<Folder> folderTreeSelectionModel;
245
    FolderTreeViewModel folderTreeViewModel;
246
    FolderTreeView folderTreeView;
247

    
248
    SingleSelectionModel<Folder> mysharedTreeSelectionModel;
249
    MysharedTreeViewModel mysharedTreeViewModel;
250
    MysharedTreeView mysharedTreeView = null;;
251

    
252
    protected SingleSelectionModel<Folder> otherSharedTreeSelectionModel;
253
    OtherSharedTreeViewModel otherSharedTreeViewModel;
254
    OtherSharedTreeView otherSharedTreeView = null;
255

    
256
    GroupTreeViewModel groupTreeViewModel;
257
    private GroupTreeView groupTreeView;
258

    
259
    TreeView selectedTree;
260
    protected AccountResource account;
261
    
262
    Folder trash;
263
    
264
    List<Composite> treeViews = new ArrayList<Composite>();
265

    
266
    @SuppressWarnings("rawtypes") List<SingleSelectionModel> selectionModels = new ArrayList<SingleSelectionModel>();
267
    
268
    Button upload;
269
    
270
    private HTML usedBytes;
271
    
272
    private HTML totalBytes;
273
    
274
    private HTML usedPercent;
275
    
276
    private HTML numOfFiles;
277
    
278
    private Anchor refreshButton;
279

    
280
    private Anchor toolsButton;
281

    
282
        @Override
283
        public void onModuleLoad() {
284
                if (parseUserCredentials())
285
            initialize();
286
        }
287

    
288
    private void initialize() {
289
            boolean bareContent = Window.Location.getParameter("noframe") != null;
290
            String contentWidth = bareContent ? "100%" : "75%";
291

    
292
            VerticalPanel outer = new VerticalPanel();
293
        outer.setWidth("100%");
294
            if (!bareContent) {
295
                    outer.addStyleName("pithos-outer");
296
            }
297

    
298
        if (!bareContent) {
299
                topPanel = new TopPanel(this, Pithos.images);
300
                topPanel.setWidth("100%");
301
                outer.add(topPanel);
302
                outer.setCellHorizontalAlignment(topPanel, HasHorizontalAlignment.ALIGN_CENTER);
303
        }
304
        
305
        HorizontalPanel header = new HorizontalPanel();
306
        header.addStyleName("pithos-header");
307
        header.setWidth(contentWidth);
308
        if (bareContent)
309
                header.addStyleName("pithos-header-noframe");
310
        upload = new Button("Upload File", new ClickHandler() {
311
            @Override
312
            public void onClick(@SuppressWarnings("unused") ClickEvent event) {
313
                new UploadFileCommand(Pithos.this, null, getSelection()).execute();
314
            }
315
        });
316
        upload.addStyleName("pithos-uploadButton");
317
        header.add(upload);
318
        header.setCellHorizontalAlignment(upload, HasHorizontalAlignment.ALIGN_LEFT);
319
        header.setCellVerticalAlignment(upload, HasVerticalAlignment.ALIGN_MIDDLE);
320

    
321
        messagePanel.setVisible(false);
322
        header.add(messagePanel);
323
        header.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
324
        header.setCellVerticalAlignment(messagePanel, HasVerticalAlignment.ALIGN_MIDDLE);
325

    
326
        FlowPanel toolbar = new FlowPanel();
327
        toolbar.getElement().setId("toolbar");
328
        toolbar.addStyleName("clearfix");
329
        toolbar.getElement().getStyle().setDisplay(Display.BLOCK);
330

    
331
        Anchor newFolderButton = new Anchor("<span class='ico'></span><span class='title'>New folder</span>", true);
332
        newFolderButton.getElement().setId("newfolder-button");
333
        newFolderButton.addStyleName("pithos-toolbarItem");
334
        newFolderButton.addClickHandler(new ClickHandler() {
335
                        
336
                        @Override
337
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
338
                                Folder folder = getSelectedTree().getSelection();
339
                                if (folder != null) {
340
                                Boolean[] permissions = folder.getPermissions().get(getUsername());
341
                                    boolean canWrite = folder.getOwner().equals(getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
342
                                    
343
                                    if (!folder.isInTrash() && canWrite)
344
                                            new NewFolderCommand(Pithos.this, null, folder).execute();
345
                                }
346
                        }
347
                });
348
        toolbar.add(newFolderButton);
349

    
350
        refreshButton = new Anchor("<span class='ico'></span><span class='title'>Refresh</span>", true);
351
        refreshButton.getElement().setId("refresh-button");
352
        refreshButton.addStyleName("pithos-toolbarItem");
353
        refreshButton.addClickHandler(new ClickHandler() {
354
                        
355
                        @Override
356
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
357
                            boolean isFolderTreeSelected = selectedTree.equals(getFolderTreeView());
358
                            boolean otherSharedTreeSelected = selectedTree.equals(getOtherSharedTreeView());
359
                            Folder folder = getSelectedTree().getSelection();
360
                            
361
                            if (folder != null && (isFolderTreeSelected || otherSharedTreeSelected))
362
                                    updateFolder(folder, true, new Command() {
363
                                            
364
                                            @Override
365
                                            public void execute() {
366
                                                    updateStatistics();
367
                                            }
368
                                    });
369
                        }
370
                });
371
        toolbar.add(refreshButton);
372

    
373
        toolsButton = new Anchor("<span class='ico'></span><span class='title'>More...</span>", true);
374
        toolsButton.getElement().setId("tools-button");
375
        toolsButton.addStyleName("pithos-toolbarItem");
376
        toolsButton.addClickHandler(new ClickHandler() {
377
                        
378
                        @Override
379
                        public void onClick(ClickEvent event) {
380
                ToolsMenu menu = new ToolsMenu(Pithos.this, images, getSelectedTree(), getSelectedTree().getSelection(), getFileList().getSelectedFiles());
381
                if (!menu.isEmpty()) {
382
                            menu.setPopupPosition(event.getClientX(), event.getClientY());
383
                            menu.show();
384
                }
385
                        }
386
                });
387
        toolbar.add(toolsButton);
388
  
389
        header.add(toolbar);
390
        header.setCellHorizontalAlignment(toolbar, HasHorizontalAlignment.ALIGN_CENTER);
391
        header.setCellVerticalAlignment(toolbar, HasVerticalAlignment.ALIGN_MIDDLE);
392
//        header.setCellWidth(toolbar, "40px");
393
        
394
        HorizontalPanel folderStatistics = new HorizontalPanel();
395
        folderStatistics.addStyleName("pithos-folderStatistics");
396
        numOfFiles = new HTML();
397
        folderStatistics.add(numOfFiles);
398
        folderStatistics.setCellVerticalAlignment(numOfFiles, HasVerticalAlignment.ALIGN_MIDDLE);
399
        HTML numOfFilesLabel = new HTML("&nbsp;Files");
400
        folderStatistics.add(numOfFilesLabel);
401
        folderStatistics.setCellVerticalAlignment(numOfFilesLabel, HasVerticalAlignment.ALIGN_MIDDLE);
402
        header.add(folderStatistics);
403
        header.setCellHorizontalAlignment(folderStatistics, HasHorizontalAlignment.ALIGN_RIGHT);
404
        header.setCellVerticalAlignment(folderStatistics, HasVerticalAlignment.ALIGN_MIDDLE);
405
        header.setCellWidth(folderStatistics, "40px");
406
        outer.add(header);
407
        outer.setCellHorizontalAlignment(header, HasHorizontalAlignment.ALIGN_CENTER);
408
        // Inner contains the various lists.nner
409
        inner.sinkEvents(Event.ONCONTEXTMENU);
410
        inner.setWidth("100%");
411

    
412
        folderTreeSelectionModel = new SingleSelectionModel<Folder>();
413
        folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
414
            @Override
415
            public void onSelectionChange(@SuppressWarnings("unused") SelectionChangeEvent event) {
416
                if (folderTreeSelectionModel.getSelectedObject() != null) {
417
                    deselectOthers(folderTreeView, folderTreeSelectionModel);
418
                    applyPermissions(folderTreeSelectionModel.getSelectedObject());
419
                    Folder f = folderTreeSelectionModel.getSelectedObject();
420
                            updateFolder(f, true, new Command() {
421
                                    
422
                                    @Override
423
                                    public void execute() {
424
                                            updateStatistics();
425
                                    }
426
                            });
427
                }
428
            }
429
        });
430
        selectionModels.add(folderTreeSelectionModel);
431

    
432
        folderTreeViewModel = new FolderTreeViewModel(this, folderTreeSelectionModel);
433
        folderTreeView = new FolderTreeView(folderTreeViewModel);
434
        treeViews.add(folderTreeView);
435
        
436
        fileList = new FileList(this, images, folderTreeView);
437
        inner.add(fileList);
438

    
439
        groupTreeViewModel = new GroupTreeViewModel(this);
440
        groupTreeView = new GroupTreeView(groupTreeViewModel);
441
        treeViews.add(groupTreeView);
442
        
443
        trees = new VerticalPanel();
444
        trees.setWidth("100%");
445

    
446
        
447
        HorizontalPanel treeHeader = new HorizontalPanel();
448
        treeHeader.addStyleName("pithos-treeHeader");
449
        treeHeader.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
450
        treeHeader.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
451
        HorizontalPanel statistics = new HorizontalPanel();
452
        statistics.addStyleName("pithos-statistics");
453
        statistics.add(new HTML("Used:&nbsp;"));
454
        usedBytes = new HTML();
455
        statistics.add(usedBytes);
456
        statistics.add(new HTML("&nbsp;of&nbsp;"));
457
        totalBytes = new HTML();
458
        statistics.add(totalBytes);
459
        statistics.add(new HTML("&nbsp;("));
460
        usedPercent = new HTML();
461
        statistics.add(usedPercent);
462
        statistics.add(new HTML(")"));
463
        treeHeader.add(statistics);
464
        treeHeader.setCellHorizontalAlignment(statistics, HasHorizontalAlignment.ALIGN_LEFT);
465
        trees.add(treeHeader);
466

    
467
        trees.add(folderTreeView);
468
        trees.add(groupTreeView);
469
        // Add the left and right panels to the split panel.
470
        splitPanel.setLeftWidget(trees);
471
        splitPanel.setRightWidget(inner);
472
        splitPanel.setSplitPosition("35%");
473
        splitPanel.setSize("100%", "100%");
474
        splitPanel.addStyleName("pithos-splitPanel");
475
        splitPanel.setWidth(contentWidth);
476
        outer.add(splitPanel);
477
        outer.setCellHorizontalAlignment(splitPanel, HasHorizontalAlignment.ALIGN_CENTER);
478

    
479
        if (!bareContent) {
480
                statusPanel = new StatusPanel();
481
                statusPanel.setWidth("100%");
482
                outer.add(statusPanel);
483
                outer.setCellHorizontalAlignment(statusPanel, HasHorizontalAlignment.ALIGN_CENTER);
484
        }
485
        else
486
                splitPanel.addStyleName("pithos-splitPanel-noframe");
487

    
488
        // Hook the window resize event, so that we can adjust the UI.
489
        Window.addResizeHandler(this);
490
        // Clear out the window's built-in margin, because we want to take
491
        // advantage of the entire client area.
492
        Window.setMargin("0px");
493
        // Finally, add the outer panel to the RootPanel, so that it will be
494
        // displayed.
495
        RootPanel.get().add(outer);
496
        // Call the window resized handler to get the initial sizes setup. Doing
497
        // this in a deferred command causes it to occur after all widgets'
498
        // sizes have been computed by the browser.
499
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
500

    
501
            @Override
502
            public void execute() {
503
                onWindowResized(Window.getClientHeight());
504
            }
505
        });
506

    
507
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
508
            @Override
509
            public void execute() {
510
                fetchAccount(new Command() {
511
                                        
512
                                        @Override
513
                                        public void execute() {
514
                                if (!account.hasHomeContainer())
515
                                    createHomeContainer(account, this);
516
                                else if (!account.hasTrashContainer())
517
                                        createTrashContainer(this);
518
                                else {
519
                                        for (Folder f : account.getContainers())
520
                                                if (f.getName().equals(Pithos.TRASH_CONTAINER)) {
521
                                                        trash = f;
522
                                                        break;
523
                                                }
524
                                    folderTreeViewModel.initialize(account, new Command() {
525
                                                                
526
                                                                @Override
527
                                                                public void execute() {
528
                                                    createMySharedTree();
529
                                                                }
530
                                                        });
531
                                    groupTreeViewModel.initialize();
532
                                    showStatistics();
533
                                }
534
                                        }
535
                                });
536
            }
537
        });
538
        
539
//        Scheduler.get().scheduleDeferred(new Command() {
540
//                        
541
//                        @Override
542
//                        public void execute() {
543
//                                displayError("lalala");
544
//                                
545
//                        }
546
//                });
547
    }
548

    
549
    public void applyPermissions(Folder f) {
550
            if (f != null) {
551
                    if (f.isInTrash())
552
                            upload.setEnabled(false);
553
                    else {
554
                            Boolean[] perms = f.getPermissions().get(username);
555
                            if (f.getOwner().equals(username) || (perms != null && perms[1] != null && perms[1])) {
556
                                    upload.setEnabled(true);
557
                            }
558
                            else
559
                                    upload.setEnabled(false);
560
                    }
561
            }
562
            else
563
                    upload.setEnabled(false);
564
        }
565

    
566
        @SuppressWarnings({ "rawtypes", "unchecked" })
567
        public void deselectOthers(TreeView _selectedTree, SingleSelectionModel model) {
568
            selectedTree = _selectedTree;
569
            
570
            for (Composite c : treeViews)
571
                    if (c.equals(selectedTree))
572
                            c.addStyleName("cellTreeWidget-selectedTree");
573
                    else
574
                            c.removeStyleName("cellTreeWidget-selectedTree");
575
            
576
        for (SingleSelectionModel s : selectionModels)
577
            if (!s.equals(model))
578
                s.setSelected(s.getSelectedObject(), false);
579
    }
580

    
581
    public void showFiles(final Folder f) {
582
        Set<File> files = f.getFiles();
583
        showFiles(files);
584
    }
585

    
586
    public void showFiles(Set<File> files) {
587
        fileList.setFiles(new ArrayList<File>(files));
588
    }
589

    
590
    protected void fetchFile(final Iterator<File> iter, final Set<File> files) {
591
        if (iter.hasNext()) {
592
            File file = iter.next();
593
            String path = file.getUri() + "?format=json";
594
            GetRequest<File> getFile = new GetRequest<File>(File.class, getApiPath(), username, path, file) {
595
                @Override
596
                public void onSuccess(@SuppressWarnings("unused") File _result) {
597
                    fetchFile(iter, files);
598
                }
599

    
600
                @Override
601
                public void onError(Throwable t) {
602
                    GWT.log("Error getting file", t);
603
                                        setError(t);
604
                    if (t instanceof RestException)
605
                        displayError("Error getting file: " + ((RestException) t).getHttpStatusText());
606
                    else
607
                        displayError("System error fetching file: " + t.getMessage());
608
                }
609

    
610
                                @Override
611
                                protected void onUnauthorized(Response response) {
612
                                        sessionExpired();
613
                                }
614
            };
615
            getFile.setHeader("X-Auth-Token", "0000");
616
            Scheduler.get().scheduleDeferred(getFile);
617
        }
618
        else
619
            fileList.setFiles(new ArrayList<File>(files));
620
    }
621

    
622
    /**
623
         * Parse and store the user credentials to the appropriate fields.
624
         */
625
        private boolean parseUserCredentials() {
626
        username = Window.Location.getParameter("user");
627
        token = Window.Location.getParameter("token");
628
        Configuration conf = (Configuration) GWT.create(Configuration.class);
629
        if (username == null || username.length() == 0 || token == null || token.length() == 0) {
630
            String cookie = conf.authCookie();
631
            String auth = Cookies.getCookie(cookie);
632
            if (auth == null) {
633
                authenticateUser();
634
                return false;
635
            }
636
            if (auth.startsWith("\""))
637
                    auth = auth.substring(1);
638
            if (auth.endsWith("\""))
639
                    auth = auth.substring(0, auth.length() - 1);
640
                        String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
641
                        if (authSplit.length != 2) {
642
                            authenticateUser();
643
                            return false;
644
                        }
645
                        username = authSplit[0];
646
                        token = authSplit[1];
647
                        return true;
648
        }
649
        
650
                Cookies.setCookie(conf.authCookie(), username + conf.cookieSeparator() + token, null, "", "/", false);
651
                return true;
652
    }
653

    
654
    /**
655
         * Redirect the user to the login page for authentication.
656
         */
657
        protected void authenticateUser() {
658
                Configuration conf = (Configuration) GWT.create(Configuration.class);
659
        Window.Location.assign(conf.loginUrl() + "?next=" + Window.Location.getHref());
660
        }
661

    
662
        protected void fetchAccount(final Command callback) {
663
        String path = "?format=json";
664

    
665
        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, getApiPath(), username, path) {
666
            @Override
667
            public void onSuccess(AccountResource _result) {
668
                account = _result;
669
                if (callback != null)
670
                        callback.execute();
671
            }
672

    
673
            @Override
674
            public void onError(Throwable t) {
675
                GWT.log("Error getting account", t);
676
                                setError(t);
677
                if (t instanceof RestException)
678
                    displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
679
                else
680
                    displayError("System error fetching user data: " + t.getMessage());
681
            }
682

    
683
                        @Override
684
                        protected void onUnauthorized(Response response) {
685
                                sessionExpired();
686
                        }
687
        };
688
        getAccount.setHeader("X-Auth-Token", token);
689
        Scheduler.get().scheduleDeferred(getAccount);
690
    }
691

    
692
    public void updateStatistics() {
693
            HeadRequest<AccountResource> headAccount = new HeadRequest<AccountResource>(AccountResource.class, getApiPath(), username, "", account) {
694

    
695
                        @Override
696
                        public void onSuccess(@SuppressWarnings("unused") AccountResource _result) {
697
                                showStatistics();
698
                        }
699

    
700
                        @Override
701
                        public void onError(Throwable t) {
702
                GWT.log("Error getting account", t);
703
                                setError(t);
704
                if (t instanceof RestException)
705
                    displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
706
                else
707
                    displayError("System error fetching user data: " + t.getMessage());
708
                        }
709

    
710
                        @Override
711
                        protected void onUnauthorized(Response response) {
712
                                sessionExpired();
713
                        }
714
                };
715
                headAccount.setHeader("X-Auth-Token", token);
716
                Scheduler.get().scheduleDeferred(headAccount);
717
        }
718

    
719
        protected void showStatistics() {
720
            usedBytes.setHTML(String.valueOf(account.getFileSizeAsString()));
721
            totalBytes.setHTML(String.valueOf(account.getQuotaAsString()));
722
            NumberFormat nf = NumberFormat.getPercentFormat();
723
            usedPercent.setHTML(nf.format(account.getUsedPercentage()));
724
        }
725

    
726
        protected void createHomeContainer(final AccountResource _account, final Command callback) {
727
        String path = "/" + Pithos.HOME_CONTAINER;
728
        PutRequest createPithos = new PutRequest(getApiPath(), getUsername(), path) {
729
            @Override
730
            public void onSuccess(@SuppressWarnings("unused") Resource result) {
731
                    if (!_account.hasTrashContainer())
732
                            createTrashContainer(callback);
733
                    else
734
                            fetchAccount(callback);
735
            }
736

    
737
            @Override
738
            public void onError(Throwable t) {
739
                GWT.log("Error creating pithos", t);
740
                                setError(t);
741
                if (t instanceof RestException)
742
                    displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
743
                else
744
                    displayError("System error Error creating pithos: " + t.getMessage());
745
            }
746

    
747
                        @Override
748
                        protected void onUnauthorized(Response response) {
749
                                sessionExpired();
750
                        }
751
        };
752
        createPithos.setHeader("X-Auth-Token", getToken());
753
        Scheduler.get().scheduleDeferred(createPithos);
754
    }
755

    
756
    protected void createTrashContainer(final Command callback) {
757
        String path = "/" + Pithos.TRASH_CONTAINER;
758
        PutRequest createPithos = new PutRequest(getApiPath(), getUsername(), path) {
759
            @Override
760
            public void onSuccess(@SuppressWarnings("unused") Resource result) {
761
                           fetchAccount(callback);
762
            }
763

    
764
            @Override
765
            public void onError(Throwable t) {
766
                GWT.log("Error creating pithos", t);
767
                                setError(t);
768
                if (t instanceof RestException)
769
                    displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
770
                else
771
                    displayError("System error Error creating pithos: " + t.getMessage());
772
            }
773

    
774
                        @Override
775
                        protected void onUnauthorized(Response response) {
776
                                sessionExpired();
777
                        }
778
        };
779
        createPithos.setHeader("X-Auth-Token", getToken());
780
        Scheduler.get().scheduleDeferred(createPithos);
781
    }
782

    
783
    /**
784
         * Creates an HTML fragment that places an image & caption together, for use
785
         * in a group header.
786
         *
787
         * @param imageProto an image prototype for an image
788
         * @param caption the group caption
789
         * @return the header HTML fragment
790
         */
791
        private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
792
                String captionHTML = "<table class='caption' cellpadding='0' " 
793
                + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML() 
794
                + "</td><td id =" + caption +" class='rcaption'><b style='white-space:nowrap'>&nbsp;" 
795
                + caption + "</b></td></tr></table>";
796
                return captionHTML;
797
        }
798

    
799
        protected void onWindowResized(int height) {
800
                // Adjust the split panel to take up the available room in the window.
801
                int newHeight = height - splitPanel.getAbsoluteTop();
802
                if (newHeight < 1)
803
                        newHeight = 1;
804
                splitPanel.setHeight("" + newHeight);
805
                inner.setHeight("" + newHeight);
806
        }
807

    
808
        @Override
809
        public void onResize(ResizeEvent event) {
810
                int height = event.getHeight();
811
                onWindowResized(height);
812
        }
813

    
814
        /**
815
         * Display an error message.
816
         *
817
         * @param msg the message to display
818
         */
819
        public void displayError(String msg) {
820
                messagePanel.displayError(msg);
821
        }
822

    
823
        /**
824
         * Display a warning message.
825
         *
826
         * @param msg the message to display
827
         */
828
        public void displayWarning(String msg) {
829
                messagePanel.displayWarning(msg);
830
        }
831

    
832
        /**
833
         * Display an informational message.
834
         *
835
         * @param msg the message to display
836
         */
837
        public void displayInformation(String msg) {
838
                messagePanel.displayInformation(msg);
839
        }
840

    
841
        /**
842
         * Retrieve the fileList.
843
         *
844
         * @return the fileList
845
         */
846
        public FileList getFileList() {
847
                return fileList;
848
        }
849

    
850
        /**
851
         * Retrieve the topPanel.
852
         *
853
         * @return the topPanel
854
         */
855
        TopPanel getTopPanel() {
856
                return topPanel;
857
        }
858

    
859
        /**
860
         * Retrieve the clipboard.
861
         *
862
         * @return the clipboard
863
         */
864
        public Clipboard getClipboard() {
865
                return clipboard;
866
        }
867

    
868
        public StatusPanel getStatusPanel() {
869
                return statusPanel;
870
        }
871

    
872
        public String getToken() {
873
                return token;
874
        }
875

    
876
        public static native void preventIESelection() /*-{
877
                $doc.body.onselectstart = function () { return false; };
878
        }-*/;
879

    
880
        public static native void enableIESelection() /*-{
881
                if ($doc.body.onselectstart != null)
882
                $doc.body.onselectstart = null;
883
        }-*/;
884

    
885
        /**
886
         * @return the absolute path of the API root URL
887
         */
888
        public String getApiPath() {
889
                Configuration conf = (Configuration) GWT.create(Configuration.class);
890
                return conf.apiPath();
891
        }
892

    
893
        /**
894
         * History support for folder navigation
895
         * adds a new browser history entry
896
         *
897
         * @param key
898
         */
899
        public void updateHistory(String key){
900
//                Replace any whitespace of the initial string to "+"
901
//                String result = key.replaceAll("\\s","+");
902
//                Add a new browser history entry.
903
//                History.newItem(result);
904
                History.newItem(key);
905
        }
906

    
907
    public void deleteFolder(final Folder folder) {
908
        String path = getApiPath() + folder.getOwner() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(folder.getPrefix()) + "&t=" + System.currentTimeMillis();
909
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
910
        builder.setHeader("X-Auth-Token", getToken());
911
        try {
912
            builder.sendRequest("", new RequestCallback() {
913
                @Override
914
                public void onResponseReceived(@SuppressWarnings("unused") Request request, Response response) {
915
                    if (response.getStatusCode() == Response.SC_OK) {
916
                        JSONValue json = JSONParser.parseStrict(response.getText());
917
                        JSONArray array = json.isArray();
918
                        int i = 0;
919
                        if (array != null) {
920
                            deleteObject(folder, i, array);
921
                        }
922
                    }
923
                }
924

    
925
                @Override
926
                public void onError(@SuppressWarnings("unused") Request request, Throwable exception) {
927
                        setError(exception);
928
                    displayError("System error unable to delete folder: " + exception.getMessage());
929
                }
930
            });
931
        }
932
        catch (RequestException e) {
933
        }
934
    }
935

    
936
    void deleteObject(final Folder folder, final int i, final JSONArray array) {
937
        if (i < array.size()) {
938
            JSONObject o = array.get(i).isObject();
939
            if (o != null && !o.containsKey("subdir")) {
940
                JSONString name = o.get("name").isString();
941
                String path = "/" + folder.getContainer() + "/" + name.stringValue();
942
                DeleteRequest delete = new DeleteRequest(getApiPath(), folder.getOwner(), path) {
943
                    @Override
944
                    public void onSuccess(@SuppressWarnings("unused") Resource result) {
945
                        deleteObject(folder, i + 1, array);
946
                    }
947

    
948
                    @Override
949
                    public void onError(Throwable t) {
950
                        GWT.log("", t);
951
                                                setError(t);
952
                        displayError("System error unable to delete folder: " + t.getMessage());
953
                    }
954

    
955
                                    @Override
956
                                    protected void onUnauthorized(Response response) {
957
                                            sessionExpired();
958
                                    }
959
                };
960
                delete.setHeader("X-Auth-Token", getToken());
961
                Scheduler.get().scheduleDeferred(delete);
962
            }
963
            else if (o != null) {
964
                String subdir = o.get("subdir").isString().stringValue();
965
                subdir = subdir.substring(0, subdir.length() - 1);
966
                String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(subdir) + "&t=" + System.currentTimeMillis();
967
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
968
                builder.setHeader("X-Auth-Token", getToken());
969
                try {
970
                    builder.sendRequest("", new RequestCallback() {
971
                        @Override
972
                        public void onResponseReceived(@SuppressWarnings("unused") Request request, Response response) {
973
                            if (response.getStatusCode() == Response.SC_OK) {
974
                                JSONValue json = JSONParser.parseStrict(response.getText());
975
                                JSONArray array2 = json.isArray();
976
                                if (array2 != null) {
977
                                    int l = array.size();
978
                                    for (int j=0; j<array2.size(); j++) {
979
                                        array.set(l++, array2.get(j));
980
                                    }
981
                                }
982
                                deleteObject(folder, i + 1, array);
983
                            }
984
                        }
985

    
986
                        @Override
987
                        public void onError(@SuppressWarnings("unused") Request request, Throwable exception) {
988
                                setError(exception);
989
                            displayError("System error unable to delete folder: " + exception.getMessage());
990
                        }
991
                    });
992
                }
993
                catch (RequestException e) {
994
                }
995
            }
996
        }
997
        else {
998
            String path = folder.getUri();
999
            DeleteRequest deleteFolder = new DeleteRequest(getApiPath(), getUsername(), path) {
1000
                @Override
1001
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
1002
                    updateFolder(folder.getParent(), true, new Command() {
1003
                                                
1004
                                                @Override
1005
                                                public void execute() {
1006
                                                        updateStatistics();
1007
                                                }
1008
                                        });
1009
                }
1010

    
1011
                @Override
1012
                public void onError(Throwable t) {
1013
                    GWT.log("", t);
1014
                                        setError(t);
1015
                    if (t instanceof RestException) {
1016
                            if (((RestException) t).getHttpStatusCode() != Response.SC_NOT_FOUND)
1017
                                    displayError("Unable to delete folder: "+((RestException) t).getHttpStatusText());
1018
                            else
1019
                                    onSuccess(null);
1020
                    }
1021
                    else
1022
                        displayError("System error unable to delete folder: " + t.getMessage());
1023
                }
1024

    
1025
                                @Override
1026
                                protected void onUnauthorized(Response response) {
1027
                                        sessionExpired();
1028
                                }
1029
            };
1030
            deleteFolder.setHeader("X-Auth-Token", getToken());
1031
            Scheduler.get().scheduleDeferred(deleteFolder);
1032
        }
1033
    }
1034

    
1035
    public FolderTreeView getFolderTreeView() {
1036
        return folderTreeView;
1037
    }
1038

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

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

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

    
1077
    public void copySubfolders(final Iterator<Folder> iter, final String targetUsername, final String targetUri, final Command callback) {
1078
        if (iter.hasNext()) {
1079
            final Folder f = iter.next();
1080
            copyFolder(f, targetUsername, targetUri, new Command() {
1081
                                
1082
                                @Override
1083
                                public void execute() {
1084
                                        copySubfolders(iter, targetUsername, targetUri, callback);
1085
                                }
1086
                        });
1087
        }
1088
        else  if (callback != null) {
1089
            callback.execute();
1090
        }
1091
    }
1092

    
1093
    public void copyFolder(final Folder f, final String targetUsername, final String targetUri, final Command callback) {
1094
        String path = targetUri + "/" + f.getName();
1095
        PutRequest createFolder = new PutRequest(getApiPath(), targetUsername, path) {
1096
            @Override
1097
            public void onSuccess(@SuppressWarnings("unused") Resource result) {
1098
                    GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, getApiPath(), f.getOwner(), "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix()), f) {
1099

    
1100
                                        @Override
1101
                                        public void onSuccess(final Folder _f) {
1102
                                Iterator<File> iter = _f.getFiles().iterator();
1103
                                copyFiles(iter, targetUsername, targetUri + "/" + _f.getName(), new Command() {
1104
                                    @Override
1105
                                    public void execute() {
1106
                                        Iterator<Folder> iterf = _f.getSubfolders().iterator();
1107
                                        copySubfolders(iterf, targetUsername, targetUri + "/" + _f.getName(), callback);
1108
                                    }
1109
                                });
1110
                                        }
1111

    
1112
                                        @Override
1113
                                        public void onError(Throwable t) {
1114
                                GWT.log("", t);
1115
                                                setError(t);
1116
                                if (t instanceof RestException) {
1117
                                    displayError("Unable to get folder: " + ((RestException) t).getHttpStatusText());
1118
                                }
1119
                                else
1120
                                    displayError("System error getting folder: " + t.getMessage());
1121
                                        }
1122

    
1123
                                        @Override
1124
                                        protected void onUnauthorized(Response response) {
1125
                                                sessionExpired();
1126
                                        }
1127
                                };
1128
                                getFolder.setHeader("X-Auth-Token", getToken());
1129
                                Scheduler.get().scheduleDeferred(getFolder);
1130
            }
1131

    
1132
            @Override
1133
            public void onError(Throwable t) {
1134
                GWT.log("", t);
1135
                                setError(t);
1136
               if (t instanceof RestException) {
1137
                    displayError("Unable to create folder: " + ((RestException) t).getHttpStatusText());
1138
                }
1139
                else
1140
                    displayError("System error creating folder: " + t.getMessage());
1141
            }
1142

    
1143
                        @Override
1144
                        protected void onUnauthorized(Response response) {
1145
                                sessionExpired();
1146
                        }
1147
        };
1148
        createFolder.setHeader("X-Auth-Token", getToken());
1149
        createFolder.setHeader("Accept", "*/*");
1150
        createFolder.setHeader("Content-Length", "0");
1151
        createFolder.setHeader("Content-Type", "application/folder");
1152
        Scheduler.get().scheduleDeferred(createFolder);
1153
    }
1154
    
1155
    public void addSelectionModel(@SuppressWarnings("rawtypes") SingleSelectionModel model) {
1156
            selectionModels.add(model);
1157
    }
1158

    
1159
        public OtherSharedTreeView getOtherSharedTreeView() {
1160
                return otherSharedTreeView;
1161
        }
1162

    
1163
        public void updateTrash(boolean showFiles, Command callback) {
1164
                updateFolder(trash, showFiles, callback);
1165
        }
1166

    
1167
        public void updateGroupsNode() {
1168
                groupTreeView.updateGroupNode(null);
1169
        }
1170

    
1171
        public void addGroup(String groupname) {
1172
                Group newGroup = new Group(groupname);
1173
                account.addGroup(newGroup);
1174
                groupTreeView.updateGroupNode(null);
1175
        }
1176

    
1177
        public void removeGroup(Group group) {
1178
                account.removeGroup(group);
1179
                updateGroupsNode();
1180
        }
1181

    
1182
        public TreeView getSelectedTree() {
1183
                return selectedTree;
1184
        }
1185
        
1186
        public Folder getSelection() {
1187
                return selectedTree.getSelection();
1188
        }
1189

    
1190
        public void showFolderStatistics(int folderFileCount) {
1191
                numOfFiles.setHTML(String.valueOf(folderFileCount));
1192
        }
1193

    
1194
        public GroupTreeView getGroupTreeView() {
1195
                return groupTreeView;
1196
        }
1197

    
1198
        public void sessionExpired() {
1199
                new SessionExpiredDialog(this).center();
1200
        }
1201

    
1202
        public void updateRootFolder(Command callback) {
1203
                updateFolder(account.getPithos(), false, callback);
1204
        }
1205

    
1206
        void createMySharedTree() {
1207
                mysharedTreeSelectionModel = new SingleSelectionModel<Folder>();
1208
                mysharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
1209
                    @Override
1210
                    public void onSelectionChange(@SuppressWarnings("unused") SelectionChangeEvent event) {
1211
                        if (mysharedTreeSelectionModel.getSelectedObject() != null) {
1212
                            deselectOthers(mysharedTreeView, mysharedTreeSelectionModel);
1213
                            upload.setEnabled(false);
1214
                            updateSharedFolder(mysharedTreeSelectionModel.getSelectedObject(), true);
1215
                        }
1216
                     }
1217
                });
1218
                selectionModels.add(mysharedTreeSelectionModel);
1219
                mysharedTreeViewModel = new MysharedTreeViewModel(Pithos.this, mysharedTreeSelectionModel);
1220
                mysharedTreeViewModel.initialize(new Command() {
1221
                        
1222
                        @Override
1223
                        public void execute() {
1224
                            mysharedTreeView = new MysharedTreeView(mysharedTreeViewModel);
1225
                                trees.insert(mysharedTreeView, 2);
1226
                                treeViews.add(mysharedTreeView);
1227
                                createOtherSharedTree();
1228
                        }
1229
                });
1230
        }
1231

    
1232
        void createOtherSharedTree() {
1233
                otherSharedTreeSelectionModel = new SingleSelectionModel<Folder>();
1234
                otherSharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
1235
                    @Override
1236
                    public void onSelectionChange(@SuppressWarnings("unused") SelectionChangeEvent event) {
1237
                        if (otherSharedTreeSelectionModel.getSelectedObject() != null) {
1238
                            deselectOthers(otherSharedTreeView, otherSharedTreeSelectionModel);
1239
                            otherSharedTreeView.addStyleName("cellTreeWidget-selectedTree");
1240
                            applyPermissions(otherSharedTreeSelectionModel.getSelectedObject());
1241
                            updateOtherSharedFolder(otherSharedTreeSelectionModel.getSelectedObject(), true);
1242
                        }
1243
                     }
1244
                });
1245
                selectionModels.add(otherSharedTreeSelectionModel);
1246
                otherSharedTreeViewModel = new OtherSharedTreeViewModel(Pithos.this, otherSharedTreeSelectionModel);
1247
                otherSharedTreeViewModel.initialize(new Command() {
1248
                        
1249
                        @Override
1250
                        public void execute() {
1251
                            otherSharedTreeView = new OtherSharedTreeView(otherSharedTreeViewModel);
1252
                                trees.insert(otherSharedTreeView, 3);
1253
                                treeViews.add(otherSharedTreeView);
1254
                        }
1255
                });
1256
        }
1257

    
1258
        public void logoff() {
1259
        Configuration conf = (Configuration) GWT.create(Configuration.class);
1260
                Cookies.removeCookie(conf.authCookie(), "/");
1261
                Cookies.removeCookie(conf.authTokenCookie(), "/");
1262
                for (String s: Cookies.getCookieNames())
1263
                        if (s.startsWith(conf.shibSessionCookiePrefix()))
1264
                                Cookies.removeCookie(s, "/");
1265
                Window.Location.assign(Window.Location.getPath());
1266
        }
1267

    
1268
        public String getErrorData() {
1269
                if (error != null)
1270
                        return error.toString();
1271
                return "";
1272
        }
1273
        
1274
        public void setError(Throwable t) {
1275
                error = t;
1276
        }
1277
}