Statistics
| Branch: | Tag: | Revision:

root / web_client / src / gr / grnet / pithos / web / client / Pithos.java @ 10791b56

History | View | Annotate | Download (31.5 kB)

1
/*
2
 * Copyright 2011 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
11
 *
12
 *   2. Redistributions in binary form must reproduce the above
13
 *      copyright notice, this list of conditions and the following
14
 *      disclaimer in the documentation and/or other materials
15
 *      provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * The views and conclusions contained in the software and
31
 * documentation are those of the authors and should not be
32
 * interpreted as representing official policies, either expressed
33
 * or implied, of GRNET S.A.
34
 */
35
package gr.grnet.pithos.web.client;
36

    
37
import gr.grnet.pithos.web.client.commands.UploadFileCommand;
38
import gr.grnet.pithos.web.client.foldertree.AccountResource;
39
import gr.grnet.pithos.web.client.foldertree.File;
40
import gr.grnet.pithos.web.client.foldertree.Folder;
41
import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
42
import gr.grnet.pithos.web.client.foldertree.FolderTreeViewModel;
43
import gr.grnet.pithos.web.client.foldertree.Resource;
44
import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView;
45
import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeViewModel;
46
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView;
47
import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeViewModel;
48
import gr.grnet.pithos.web.client.rest.DeleteRequest;
49
import gr.grnet.pithos.web.client.rest.GetRequest;
50
import gr.grnet.pithos.web.client.rest.PutRequest;
51
import gr.grnet.pithos.web.client.rest.RestException;
52
import gr.grnet.pithos.web.client.tagtree.Tag;
53
import gr.grnet.pithos.web.client.tagtree.TagTreeView;
54
import gr.grnet.pithos.web.client.tagtree.TagTreeViewModel;
55

    
56
import java.util.ArrayList;
57
import java.util.HashMap;
58
import java.util.Iterator;
59
import java.util.List;
60
import java.util.Set;
61

    
62
import com.google.gwt.core.client.EntryPoint;
63
import com.google.gwt.core.client.GWT;
64
import com.google.gwt.core.client.Scheduler;
65
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
66
import com.google.gwt.event.dom.client.ClickEvent;
67
import com.google.gwt.event.dom.client.ClickHandler;
68
import com.google.gwt.event.logical.shared.ResizeEvent;
69
import com.google.gwt.event.logical.shared.ResizeHandler;
70
import com.google.gwt.http.client.Request;
71
import com.google.gwt.http.client.RequestBuilder;
72
import com.google.gwt.http.client.RequestCallback;
73
import com.google.gwt.http.client.RequestException;
74
import com.google.gwt.http.client.Response;
75
import com.google.gwt.json.client.JSONArray;
76
import com.google.gwt.json.client.JSONObject;
77
import com.google.gwt.json.client.JSONParser;
78
import com.google.gwt.json.client.JSONString;
79
import com.google.gwt.json.client.JSONValue;
80
import com.google.gwt.resources.client.ImageResource;
81
import com.google.gwt.user.client.Command;
82
import com.google.gwt.user.client.Cookies;
83
import com.google.gwt.user.client.Event;
84
import com.google.gwt.user.client.History;
85
import com.google.gwt.user.client.Window;
86
import com.google.gwt.user.client.ui.AbstractImagePrototype;
87
import com.google.gwt.user.client.ui.Button;
88
import com.google.gwt.user.client.ui.HTML;
89
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
90
import com.google.gwt.user.client.ui.HasVerticalAlignment;
91
import com.google.gwt.user.client.ui.HorizontalPanel;
92
import com.google.gwt.user.client.ui.HorizontalSplitPanel;
93
import com.google.gwt.user.client.ui.Image;
94
import com.google.gwt.user.client.ui.PushButton;
95
import com.google.gwt.user.client.ui.RootPanel;
96
import com.google.gwt.user.client.ui.VerticalPanel;
97
import com.google.gwt.view.client.SelectionChangeEvent;
98
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
99
import com.google.gwt.view.client.SingleSelectionModel;
100

    
101
/**
102
 * Entry point classes define <code>onModuleLoad()</code>.
103
 */
104
public class Pithos implements EntryPoint, ResizeHandler {
105

    
106
        public static final String HOME_CONTAINER = "pithos";
107
        
108
        /**
109
         * Instantiate an application-level image bundle. This object will provide
110
         * programmatic access to all the images needed by widgets.
111
         */
112
        private static Images images = (Images) GWT.create(Images.class);
113

    
114
    public String getUsername() {
115
        return username;
116
    }
117

    
118
    public void setAccount(AccountResource acct) {
119
        account = acct;
120
    }
121

    
122
    public AccountResource getAccount() {
123
        return account;
124
    }
125

    
126
    public void updateFolder(Folder f, boolean showfiles) {
127
        folderTreeView.updateFolder(f, showfiles);
128
    }
129

    
130
    public void updateSharedFolder(Folder f, boolean showfiles) {
131
            mysharedTreeView.updateFolder(f, showfiles);
132
    }
133
    
134
    public void updateOtherSharedFolder(Folder f, boolean showfiles) {
135
            otherSharedTreeView.updateFolder(f, showfiles);
136
    }
137

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

    
142
    public void updateTags() {
143
        tagTreeViewModel.initialize(getAllTags());
144
    }
145

    
146
    public List<Tag> getAllTags() {
147
        List<Tag> tagList = new ArrayList<Tag>();
148
        for (Folder f : account.getContainers()) {
149
            for (String t : f.getTags()) {
150
                tagList.add(new Tag(t));
151
            }
152
        }
153
        return tagList;
154
    }
155

    
156
    public MysharedTreeView getMySharedTreeView() {
157
        return mysharedTreeView;
158
    }
159

    
160
    /**
161
         * An aggregate image bundle that pulls together all the images for this
162
         * application into a single bundle.
163
         */
164
        public interface Images extends TopPanel.Images, FileList.Images {
165

    
166
                @Source("gr/grnet/pithos/resources/document.png")
167
                ImageResource folders();
168

    
169
                @Source("gr/grnet/pithos/resources/edit_group_22.png")
170
                ImageResource groups();
171

    
172
                @Source("gr/grnet/pithos/resources/search.png")
173
                ImageResource search();
174
        }
175

    
176
        /**
177
         * The Application Clipboard implementation;
178
         */
179
        private Clipboard clipboard = new Clipboard();
180

    
181
        /**
182
         * The top panel that contains the menu bar.
183
         */
184
        private TopPanel topPanel;
185

    
186
        /**
187
         * The panel that contains the various system messages.
188
         */
189
        private MessagePanel messagePanel = new MessagePanel(Pithos.images);
190

    
191
        /**
192
         * The bottom panel that contains the status bar.
193
         */
194
        private StatusPanel statusPanel = null;
195

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

    
201
        /**
202
         * The tab panel that occupies the right side of the screen.
203
         */
204
        private VerticalPanel inner = new VerticalPanel();
205

    
206

    
207
        /**
208
         * The split panel that will contain the left and right panels.
209
         */
210
        private HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
211

    
212
        /**
213
         * The currently selected item in the application, for use by the Edit menu
214
         * commands. Potential types are Folder, File, User and Group.
215
         */
216
        private Object currentSelection;
217

    
218

    
219
        /**
220
         * The WebDAV password of the current user
221
         */
222
        private String webDAVPassword;
223

    
224
        public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
225

    
226
    private String username = null;
227

    
228
    /**
229
     * The authentication token of the current user.
230
     */
231
    private String token;
232

    
233
    protected SingleSelectionModel<Folder> folderTreeSelectionModel;
234
    protected FolderTreeViewModel folderTreeViewModel;
235
    protected FolderTreeView folderTreeView;
236

    
237
    protected SingleSelectionModel<Folder> mysharedTreeSelectionModel;
238
    private MysharedTreeViewModel mysharedTreeViewModel;
239
    private MysharedTreeView mysharedTreeView;
240

    
241
    protected SingleSelectionModel<Folder> otherSharedTreeSelectionModel;
242
    private OtherSharedTreeViewModel otherSharedTreeViewModel;
243
    private OtherSharedTreeView otherSharedTreeView;
244

    
245
    protected SingleSelectionModel<Tag> tagTreeSelectionModel;
246
    private TagTreeViewModel tagTreeViewModel;
247
    private TagTreeView tagTreeView;
248

    
249
    protected AccountResource account;
250

    
251
    @SuppressWarnings("rawtypes")
252
        private List<SingleSelectionModel> selectionModels = new ArrayList<SingleSelectionModel>();
253

    
254
        @Override
255
        public void onModuleLoad() {
256
                if (parseUserCredentials())
257
            initialize();
258
        }
259

    
260
    private void initialize() {
261
        VerticalPanel outer = new VerticalPanel();
262
        outer.setWidth("100%");
263

    
264
        topPanel = new TopPanel(this, Pithos.images);
265
        topPanel.setWidth("100%");
266
        outer.add(topPanel);
267

    
268
        messagePanel.setWidth("100%");
269
        messagePanel.setVisible(false);
270
        outer.add(messagePanel);
271
        outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
272

    
273

    
274
        // Inner contains the various lists.
275
        inner.sinkEvents(Event.ONCONTEXTMENU);
276
        inner.setWidth("100%");
277

    
278
        HorizontalPanel rightside = new HorizontalPanel();
279
        rightside.addStyleName("pithos-rightSide");
280
        rightside.setSpacing(5);
281

    
282
        PushButton parentButton = new PushButton(new Image(images.asc()), new ClickHandler() {
283
            @Override
284
            public void onClick(@SuppressWarnings("unused") ClickEvent event) {
285

    
286
            }
287
        });
288
        parentButton.addStyleName("pithos-parentButton");
289
        rightside.add(parentButton);
290

    
291
        HTML folderStatistics = new HTML("5 Files (size: 1.1GB)");
292
        folderStatistics.addStyleName("pithos-folderStatistics");
293
        rightside.add(folderStatistics);
294
        inner.add(rightside);
295
        inner.setCellHorizontalAlignment(rightside, HasHorizontalAlignment.ALIGN_RIGHT);
296
        inner.setCellVerticalAlignment(rightside, HasVerticalAlignment.ALIGN_MIDDLE);
297
        inner.setCellHeight(rightside, "60px");
298

    
299
        folderTreeSelectionModel = new SingleSelectionModel<Folder>();
300
        folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
301
            @Override
302
            public void onSelectionChange(@SuppressWarnings("unused") SelectionChangeEvent event) {
303
                if (folderTreeSelectionModel.getSelectedObject() != null) {
304
                    deselectOthers(folderTreeSelectionModel);
305
                    Folder f = folderTreeSelectionModel.getSelectedObject();
306
                    updateFolder(f, true);
307
                }
308
            }
309
        });
310
        selectionModels.add(folderTreeSelectionModel);
311

    
312
        folderTreeViewModel = new FolderTreeViewModel(this, folderTreeSelectionModel);
313
        folderTreeView = new FolderTreeView(folderTreeViewModel);
314

    
315
        fileList = new FileList(this, images, folderTreeView);
316
        inner.add(fileList);
317

    
318
        mysharedTreeSelectionModel = new SingleSelectionModel<Folder>();
319
        mysharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
320
            @Override
321
            public void onSelectionChange(@SuppressWarnings("unused") SelectionChangeEvent event) {
322
                if (mysharedTreeSelectionModel.getSelectedObject() != null) {
323
                    deselectOthers(mysharedTreeSelectionModel);
324
                    updateSharedFolder(mysharedTreeSelectionModel.getSelectedObject(), true);
325
                }
326
            }
327
        });
328
        selectionModels.add(mysharedTreeSelectionModel);
329
        mysharedTreeViewModel = new MysharedTreeViewModel(this, mysharedTreeSelectionModel);
330
        mysharedTreeView = new MysharedTreeView(mysharedTreeViewModel);
331

    
332
        otherSharedTreeSelectionModel = new SingleSelectionModel<Folder>();
333
        otherSharedTreeSelectionModel.addSelectionChangeHandler(new Handler() {
334
            @Override
335
            public void onSelectionChange(@SuppressWarnings("unused") SelectionChangeEvent event) {
336
                if (otherSharedTreeSelectionModel.getSelectedObject() != null) {
337
                    deselectOthers(otherSharedTreeSelectionModel);
338
                    updateOtherSharedFolder(otherSharedTreeSelectionModel.getSelectedObject(), true);
339
                }
340
            }
341
        });
342
        selectionModels.add(otherSharedTreeSelectionModel);
343
        otherSharedTreeViewModel = new OtherSharedTreeViewModel(this, otherSharedTreeSelectionModel);
344
        otherSharedTreeView = new OtherSharedTreeView(otherSharedTreeViewModel);
345

    
346
        tagTreeSelectionModel = new SingleSelectionModel<Tag>();
347
        tagTreeSelectionModel.addSelectionChangeHandler(new Handler() {
348
            @Override
349
            public void onSelectionChange(@SuppressWarnings("unused") SelectionChangeEvent event) {
350
                if (tagTreeSelectionModel.getSelectedObject() != null) {
351
                    deselectOthers(tagTreeSelectionModel);
352
                    Tag t = tagTreeSelectionModel.getSelectedObject();
353
                    updateTag(t);
354
                }
355
            }
356
        });
357
        selectionModels.add(tagTreeSelectionModel);
358
        tagTreeViewModel = new TagTreeViewModel(this, tagTreeSelectionModel);
359
        tagTreeView = new TagTreeView(tagTreeViewModel);
360

    
361
        VerticalPanel trees = new VerticalPanel();
362

    
363
        Button upload = new Button("Upload File", new ClickHandler() {
364
            @Override
365
            public void onClick(@SuppressWarnings("unused") ClickEvent event) {
366
                new UploadFileCommand(Pithos.this, null, folderTreeView.getSelection()).execute();
367
            }
368
        });
369
        upload.addStyleName("pithos-uploadButton");
370
        trees.add(upload);
371
        
372
        HorizontalPanel treeHeader = new HorizontalPanel();
373
        treeHeader.addStyleName("pithos-treeHeader");
374
        treeHeader.add(new HTML("Total Files: 6 | Used: 2.1 of 50 GB (4.2%)"));
375
        trees.add(treeHeader);
376

    
377
        trees.add(folderTreeView);
378
        trees.add(mysharedTreeView);
379
        trees.add(otherSharedTreeView);
380
//        trees.add(tagTreeView);
381
        // Add the left and right panels to the split panel.
382
        splitPanel.setLeftWidget(trees);
383
        splitPanel.setRightWidget(inner);
384
        splitPanel.setSplitPosition("25%");
385
        splitPanel.setSize("100%", "100%");
386
        splitPanel.addStyleName("pithos-splitPanel");
387
        outer.add(splitPanel);
388

    
389
        statusPanel = new StatusPanel();
390
        outer.add(statusPanel);
391

    
392

    
393
        // Hook the window resize event, so that we can adjust the UI.
394
        Window.addResizeHandler(this);
395
        // Clear out the window's built-in margin, because we want to take
396
        // advantage of the entire client area.
397
        Window.setMargin("0px");
398
        // Finally, add the outer panel to the RootPanel, so that it will be
399
        // displayed.
400
        RootPanel.get().add(outer);
401
        // Call the window resized handler to get the initial sizes setup. Doing
402
        // this in a deferred command causes it to occur after all widgets'
403
        // sizes have been computed by the browser.
404
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
405

    
406
            @Override
407
            public void execute() {
408
                onWindowResized(Window.getClientHeight());
409
            }
410
        });
411

    
412
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
413
            @Override
414
            public void execute() {
415
                fetchAccount();
416
            }
417
        });
418
    }
419

    
420
    @SuppressWarnings({ "rawtypes", "unchecked" })
421
        public void deselectOthers(SingleSelectionModel model) {
422
        for (SingleSelectionModel s : selectionModels)
423
            if (!s.equals(model))
424
                s.setSelected(s.getSelectedObject(), false);
425
    }
426

    
427
    public void showFiles(Folder f) {
428
        Set<File> files = f.getFiles();
429
        showFiles(files);
430
    }
431

    
432
    public void showFiles(Set<File> files) {
433
        //Iterator<File> iter = files.iterator();
434
        //fetchFile(iter, files);
435
        fileList.setFiles(new ArrayList<File>(files));
436
    }
437

    
438
    protected void fetchFile(final Iterator<File> iter, final Set<File> files) {
439
        if (iter.hasNext()) {
440
            File file = iter.next();
441
            String path = file.getUri() + "?format=json";
442
            GetRequest<File> getFile = new GetRequest<File>(File.class, getApiPath(), username, path, file) {
443
                @Override
444
                public void onSuccess(@SuppressWarnings("unused") File _result) {
445
                    fetchFile(iter, files);
446
                }
447

    
448
                @Override
449
                public void onError(Throwable t) {
450
                    GWT.log("Error getting file", t);
451
                    if (t instanceof RestException)
452
                        displayError("Error getting file: " + ((RestException) t).getHttpStatusText());
453
                    else
454
                        displayError("System error fetching file: " + t.getMessage());
455
                }
456
            };
457
            getFile.setHeader("X-Auth-Token", "0000");
458
            Scheduler.get().scheduleDeferred(getFile);
459
        }
460
        else
461
            fileList.setFiles(new ArrayList<File>(files));
462
    }
463

    
464
    /**
465
         * Parse and store the user credentials to the appropriate fields.
466
         */
467
        private boolean parseUserCredentials() {
468
        username = Window.Location.getParameter("user");
469
        token = Window.Location.getParameter("token");
470
        Configuration conf = (Configuration) GWT.create(Configuration.class);
471
        if (username == null || username.length() == 0 || token == null || token.length() == 0) {
472
            String cookie = conf.authCookie();
473
            String auth = Cookies.getCookie(cookie);
474
            if (auth == null) {
475
                authenticateUser();
476
                return false;
477
            }
478
                        String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
479
                        if (authSplit.length != 2) {
480
                            authenticateUser();
481
                            return false;
482
                        }
483
                        username = authSplit[0];
484
                        token = authSplit[1];
485
                        return true;
486
        }
487
                Cookies.setCookie(conf.authCookie(), username + conf.cookieSeparator() + token);
488
                return true;
489
    }
490

    
491
    /**
492
         * Redirect the user to the login page for authentication.
493
         */
494
        protected void authenticateUser() {
495
                Configuration conf = (Configuration) GWT.create(Configuration.class);
496
        Window.Location.assign(Window.Location.getHost() + conf.loginUrl() + "?next=" + Window.Location.getHref());
497
        }
498

    
499
        protected void fetchAccount() {
500
        String path = "?format=json";
501

    
502
        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, getApiPath(), username, path) {
503
            @Override
504
            public void onSuccess(AccountResource _result) {
505
                account = _result;
506
                if (account.getContainers().isEmpty())
507
                    createHomeContainers();
508
                else {
509
                    folderTreeViewModel.initialize(account);
510
                }
511
            }
512

    
513
            @Override
514
            public void onError(Throwable t) {
515
                GWT.log("Error getting account", t);
516
                if (t instanceof RestException)
517
                    displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
518
                else
519
                    displayError("System error fetching user data: " + t.getMessage());
520
            }
521
        };
522
        getAccount.setHeader("X-Auth-Token", token);
523
        Scheduler.get().scheduleDeferred(getAccount);
524
    }
525

    
526
    protected void createHomeContainers() {
527
        String path = "/pithos";
528
        PutRequest createPithos = new PutRequest(getApiPath(), getUsername(), path) {
529
            @Override
530
            public void onSuccess(@SuppressWarnings("unused") Resource result) {
531
                fetchAccount();
532
            }
533

    
534
            @Override
535
            public void onError(Throwable t) {
536
                GWT.log("Error creating pithos", t);
537
                if (t instanceof RestException)
538
                    displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
539
                else
540
                    displayError("System error Error creating pithos: " + t.getMessage());
541
            }
542
        };
543
        createPithos.setHeader("X-Auth-Token", getToken());
544
        Scheduler.get().scheduleDeferred(createPithos);
545
    }
546

    
547
        /**
548
         * Creates an HTML fragment that places an image & caption together, for use
549
         * in a group header.
550
         *
551
         * @param imageProto an image prototype for an image
552
         * @param caption the group caption
553
         * @return the header HTML fragment
554
         */
555
        private String createHeaderHTML(AbstractImagePrototype imageProto, String caption) {
556
                String captionHTML = "<table class='caption' cellpadding='0' " 
557
                + "cellspacing='0'>" + "<tr><td class='lcaption'>" + imageProto.getHTML() 
558
                + "</td><td id =" + caption +" class='rcaption'><b style='white-space:nowrap'>&nbsp;" 
559
                + caption + "</b></td></tr></table>";
560
                return captionHTML;
561
        }
562

    
563
        protected void onWindowResized(int height) {
564
                // Adjust the split panel to take up the available room in the window.
565
                int newHeight = height - splitPanel.getAbsoluteTop() - 60;
566
                if (newHeight < 1)
567
                        newHeight = 1;
568
                splitPanel.setHeight("" + newHeight);
569
                inner.setHeight("" + newHeight);
570
        }
571

    
572
        @Override
573
        public void onResize(ResizeEvent event) {
574
                int height = event.getHeight();
575
                onWindowResized(height);
576
        }
577

    
578
        /**
579
         * Display an error message.
580
         *
581
         * @param msg the message to display
582
         */
583
        public void displayError(String msg) {
584
                messagePanel.displayError(msg);
585
        }
586

    
587
        /**
588
         * Display a warning message.
589
         *
590
         * @param msg the message to display
591
         */
592
        public void displayWarning(String msg) {
593
                messagePanel.displayWarning(msg);
594
        }
595

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

    
605
        /**
606
         * Retrieve the fileList.
607
         *
608
         * @return the fileList
609
         */
610
        public FileList getFileList() {
611
                return fileList;
612
        }
613

    
614
        /**
615
         * Retrieve the topPanel.
616
         *
617
         * @return the topPanel
618
         */
619
        TopPanel getTopPanel() {
620
                return topPanel;
621
        }
622

    
623
        /**
624
         * Retrieve the clipboard.
625
         *
626
         * @return the clipboard
627
         */
628
        public Clipboard getClipboard() {
629
                return clipboard;
630
        }
631

    
632
        public StatusPanel getStatusPanel() {
633
                return statusPanel;
634
        }
635

    
636
        public String getToken() {
637
                return token;
638
        }
639

    
640
        public String getWebDAVPassword() {
641
                return webDAVPassword;
642
        }
643

    
644
        public static native void preventIESelection() /*-{
645
                $doc.body.onselectstart = function () { return false; };
646
        }-*/;
647

    
648
        public static native void enableIESelection() /*-{
649
                if ($doc.body.onselectstart != null)
650
                $doc.body.onselectstart = null;
651
        }-*/;
652

    
653
        /**
654
         * @return the absolute path of the API root URL
655
         */
656
        public String getApiPath() {
657
                Configuration conf = (Configuration) GWT.create(Configuration.class);
658
                return conf.apiPath();
659
        }
660

    
661
        /**
662
         * History support for folder navigation
663
         * adds a new browser history entry
664
         *
665
         * @param key
666
         */
667
        public void updateHistory(String key){
668
//                Replace any whitespace of the initial string to "+"
669
//                String result = key.replaceAll("\\s","+");
670
//                Add a new browser history entry.
671
//                History.newItem(result);
672
                History.newItem(key);
673
        }
674

    
675
    public void deleteFolder(final Folder folder) {
676
        String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + folder.getPrefix();
677
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
678
        builder.setHeader("If-Modified-Since", "0");
679
        builder.setHeader("X-Auth-Token", getToken());
680
        try {
681
            builder.sendRequest("", new RequestCallback() {
682
                @Override
683
                public void onResponseReceived(@SuppressWarnings("unused") Request request, Response response) {
684
                    if (response.getStatusCode() == Response.SC_OK) {
685
                        JSONValue json = JSONParser.parseStrict(response.getText());
686
                        JSONArray array = json.isArray();
687
                        int i = 0;
688
                        if (array != null) {
689
                            deleteObject(folder, i, array);
690
                        }
691
                    }
692
                }
693

    
694
                @Override
695
                public void onError(@SuppressWarnings("unused") Request request, Throwable exception) {
696
                    displayError("System error unable to delete folder: " + exception.getMessage());
697
                }
698
            });
699
        }
700
        catch (RequestException e) {
701
        }
702
    }
703

    
704
    public void deleteObject(final Folder folder, final int i, final JSONArray array) {
705
        if (i < array.size()) {
706
            JSONObject o = array.get(i).isObject();
707
            if (o != null && !o.containsKey("subdir")) {
708
                JSONString name = o.get("name").isString();
709
                String path = "/" + folder.getContainer() + "/" + name.stringValue();
710
                DeleteRequest delete = new DeleteRequest(getApiPath(), getUsername(), path) {
711
                    @Override
712
                    public void onSuccess(@SuppressWarnings("unused") Resource result) {
713
                        deleteObject(folder, i + 1, array);
714
                    }
715

    
716
                    @Override
717
                    public void onError(Throwable t) {
718
                        GWT.log("", t);
719
                        displayError("System error unable to delete folder: " + t.getMessage());
720
                    }
721
                };
722
                delete.setHeader("X-Auth-Token", getToken());
723
                Scheduler.get().scheduleDeferred(delete);
724
            }
725
            else if (o != null) {
726
                String subdir = o.get("subdir").isString().stringValue();
727
                subdir = subdir.substring(0, subdir.length() - 1);
728
                String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + subdir;
729
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
730
                builder.setHeader("If-Modified-Since", "0");
731
                builder.setHeader("X-Auth-Token", getToken());
732
                try {
733
                    builder.sendRequest("", new RequestCallback() {
734
                        @Override
735
                        public void onResponseReceived(@SuppressWarnings("unused") Request request, Response response) {
736
                            if (response.getStatusCode() == Response.SC_OK) {
737
                                JSONValue json = JSONParser.parseStrict(response.getText());
738
                                JSONArray array2 = json.isArray();
739
                                if (array2 != null) {
740
                                    int l = array.size();
741
                                    for (int j=0; j<array2.size(); j++) {
742
                                        array.set(l++, array2.get(j));
743
                                    }
744
                                }
745
                                deleteObject(folder, i + 1, array);
746
                            }
747
                        }
748

    
749
                        @Override
750
                        public void onError(@SuppressWarnings("unused") Request request, Throwable exception) {
751
                            displayError("System error unable to delete folder: " + exception.getMessage());
752
                        }
753
                    });
754
                }
755
                catch (RequestException e) {
756
                }
757
            }
758
        }
759
        else {
760
            String path = folder.getUri();
761
            DeleteRequest deleteFolder = new DeleteRequest(getApiPath(), getUsername(), path) {
762
                @Override
763
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
764
                    updateFolder(folder.getParent(), true);
765
                }
766

    
767
                @Override
768
                public void onError(Throwable t) {
769
                    GWT.log("", t);
770
                    if (t instanceof RestException) {
771
                        displayError("Unable to delete folder: "+((RestException) t).getHttpStatusText());
772
                    }
773
                    else
774
                        displayError("System error unable to delete folder: " + t.getMessage());
775
                }
776
            };
777
            deleteFolder.setHeader("X-Auth-Token", getToken());
778
            Scheduler.get().scheduleDeferred(deleteFolder);
779
        }
780
    }
781

    
782
    public FolderTreeView getFolderTreeView() {
783
        return folderTreeView;
784
    }
785

    
786
    public void copyFiles(final Iterator<File> iter, final String targetUri, final Command callback) {
787
        if (iter.hasNext()) {
788
            File file = iter.next();
789
            String path = targetUri + "/" + file.getName();
790
            PutRequest copyFile = new PutRequest(getApiPath(), getUsername(), path) {
791
                @Override
792
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
793
                    copyFiles(iter, targetUri, callback);
794
                }
795

    
796
                @Override
797
                public void onError(Throwable t) {
798
                    GWT.log("", t);
799
                    if (t instanceof RestException) {
800
                        displayError("Unable to copy file: " + ((RestException) t).getHttpStatusText());
801
                    }
802
                    else
803
                        displayError("System error unable to copy file: "+t.getMessage());
804
                }
805
            };
806
            copyFile.setHeader("X-Auth-Token", getToken());
807
            copyFile.setHeader("X-Copy-From", file.getUri());
808
            Scheduler.get().scheduleDeferred(copyFile);
809
        }
810
        else  if (callback != null) {
811
            callback.execute();
812
        }
813
    }
814

    
815
    public void copySubfolders(final Iterator<Folder> iter, final String targetUri, final Command callback) {
816
        if (iter.hasNext()) {
817
            final Folder f = iter.next();
818
            copyFolder(f, targetUri, callback);
819
        }
820
        else  if (callback != null) {
821
            callback.execute();
822
        }
823
    }
824

    
825
    public void copyFolder(final Folder f, final String targetUri, final Command callback) {
826
        String path = targetUri + "/" + f.getName();
827
        PutRequest createFolder = new PutRequest(getApiPath(), getUsername(), path) {
828
            @Override
829
            public void onSuccess(@SuppressWarnings("unused") Resource result) {
830
                Iterator<File> iter = f.getFiles().iterator();
831
                copyFiles(iter, targetUri + "/" + f.getName(), new Command() {
832
                    @Override
833
                    public void execute() {
834
                        Iterator<Folder> iterf = f.getSubfolders().iterator();
835
                        copySubfolders(iterf, targetUri + "/" + f.getName(), new Command() {
836
                            @Override
837
                            public void execute() {
838
                                callback.execute();
839
                            }
840
                        });
841
                    }
842
                });
843
            }
844

    
845
            @Override
846
            public void onError(Throwable t) {
847
                GWT.log("", t);
848
                if (t instanceof RestException) {
849
                    displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());
850
                }
851
                else
852
                    displayError("System error creating folder:" + t.getMessage());
853
            }
854
        };
855
        createFolder.setHeader("X-Auth-Token", getToken());
856
        createFolder.setHeader("Accept", "*/*");
857
        createFolder.setHeader("Content-Length", "0");
858
        createFolder.setHeader("Content-Type", "application/folder");
859
        Scheduler.get().scheduleDeferred(createFolder);
860
    }
861
    
862
    public void addSelectionModel(@SuppressWarnings("rawtypes") SingleSelectionModel model) {
863
            selectionModels.add(model);
864
    }
865

    
866
        public OtherSharedTreeView getOtherSharedTreeView() {
867
                return otherSharedTreeView;
868
        }
869
}