Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (27.9 kB)

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

    
37
import com.google.gwt.core.client.Scheduler;
38
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
39
import com.google.gwt.http.client.Request;
40
import com.google.gwt.http.client.RequestBuilder;
41
import com.google.gwt.http.client.RequestCallback;
42
import com.google.gwt.http.client.RequestException;
43
import com.google.gwt.http.client.Response;
44
import com.google.gwt.json.client.JSONArray;
45
import com.google.gwt.json.client.JSONObject;
46
import com.google.gwt.json.client.JSONParser;
47
import com.google.gwt.json.client.JSONString;
48
import com.google.gwt.json.client.JSONValue;
49
import com.google.gwt.user.client.Command;
50
import com.google.gwt.view.client.SelectionChangeEvent;
51
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
52
import com.google.gwt.view.client.SingleSelectionModel;
53
import gr.grnet.pithos.web.client.foldertree.AccountResource;
54
import gr.grnet.pithos.web.client.foldertree.File;
55
import gr.grnet.pithos.web.client.foldertree.Folder;
56
import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
57
import gr.grnet.pithos.web.client.foldertree.FolderTreeViewModel;
58
import gr.grnet.pithos.web.client.foldertree.Resource;
59
import gr.grnet.pithos.web.client.rest.DeleteRequest;
60
import gr.grnet.pithos.web.client.rest.GetRequest;
61
import gr.grnet.pithos.web.client.rest.PutRequest;
62
import gr.grnet.pithos.web.client.rest.RestException;
63

    
64
import gr.grnet.pithos.web.client.tagtree.Tag;
65
import gr.grnet.pithos.web.client.tagtree.TagTreeView;
66
import gr.grnet.pithos.web.client.tagtree.TagTreeViewModel;
67
import java.util.ArrayList;
68
import java.util.Arrays;
69
import java.util.Date;
70
import java.util.HashMap;
71
import java.util.Iterator;
72
import java.util.List;
73

    
74
import com.google.gwt.core.client.EntryPoint;
75
import com.google.gwt.core.client.GWT;
76
import com.google.gwt.event.logical.shared.ResizeEvent;
77
import com.google.gwt.event.logical.shared.ResizeHandler;
78
import com.google.gwt.event.logical.shared.SelectionEvent;
79
import com.google.gwt.event.logical.shared.SelectionHandler;
80
import com.google.gwt.i18n.client.DateTimeFormat;
81
import com.google.gwt.resources.client.ClientBundle;
82
import com.google.gwt.resources.client.ImageResource;
83
import com.google.gwt.user.client.Cookies;
84
import com.google.gwt.user.client.Event;
85
import com.google.gwt.user.client.History;
86
import com.google.gwt.user.client.Window;
87
import com.google.gwt.user.client.ui.AbstractImagePrototype;
88
import com.google.gwt.user.client.ui.DecoratedTabPanel;
89
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
90
import com.google.gwt.user.client.ui.HorizontalSplitPanel;
91
import com.google.gwt.user.client.ui.RootPanel;
92
import com.google.gwt.user.client.ui.TabPanel;
93
import com.google.gwt.user.client.ui.VerticalPanel;
94
import java.util.Set;
95

    
96
/**
97
 * Entry point classes define <code>onModuleLoad()</code>.
98
 */
99
public class Pithos implements EntryPoint, ResizeHandler {
100

    
101
        /**
102
         * A constant that denotes the completion of an IncrementalCommand.
103
         */
104
        public static final boolean DONE = false;
105

    
106
        public static final int VISIBLE_FILE_COUNT = 25;
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 updateTag(Tag t) {
131
        tagTreeView.updateTag(t);
132
    }
133

    
134
    public void updateTags() {
135
        tagTreeViewModel.initialize(getAllTags());
136
    }
137

    
138
    public List<Tag> getAllTags() {
139
        List<Tag> tagList = new ArrayList<Tag>();
140
        for (Folder f : account.getContainers()) {
141
            for (String t : f.getTags()) {
142
                tagList.add(new Tag(t));
143
            }
144
        }
145
        return tagList;
146
    }
147

    
148
    /**
149
         * An aggregate image bundle that pulls together all the images for this
150
         * application into a single bundle.
151
         */
152
        public interface Images extends ClientBundle, TopPanel.Images, FilePropertiesDialog.Images, MessagePanel.Images, FileList.Images {
153

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

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

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

    
164
        /**
165
         * The Application Clipboard implementation;
166
         */
167
        private Clipboard clipboard = new Clipboard();
168

    
169
        /**
170
         * The top panel that contains the menu bar.
171
         */
172
        private TopPanel topPanel;
173

    
174
        /**
175
         * The panel that contains the various system messages.
176
         */
177
        private MessagePanel messagePanel = new MessagePanel(Pithos.images);
178

    
179
        /**
180
         * The bottom panel that contains the status bar.
181
         */
182
        private StatusPanel statusPanel = null;
183

    
184
        /**
185
         * The file list widget.
186
         */
187
        private FileList fileList;
188

    
189
        /**
190
         * The tab panel that occupies the right side of the screen.
191
         */
192
        private TabPanel inner = new DecoratedTabPanel(){
193
                
194
//                public void onBrowserEvent(com.google.gwt.user.client.Event event) {
195
//                        if (DOM.eventGetType(event) == Event.ONCONTEXTMENU){
196
//                                if(isFileListShowing()){
197
//                                        getFileList().showContextMenu(event);
198
//                                }
199
//                        }
200
//                };
201
        };
202

    
203

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

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

    
215

    
216
        /**
217
         * The WebDAV password of the current user
218
         */
219
        private String webDAVPassword;
220

    
221
        public HashMap<String, String> userFullNameMap = new HashMap<String, String>();
222

    
223
    private String username = null;
224

    
225
    /**
226
     * The authentication token of the current user.
227
     */
228
    private String token;
229

    
230
    private SingleSelectionModel<Folder> folderTreeSelectionModel;
231
    private FolderTreeViewModel folderTreeViewModel;
232
    private FolderTreeView folderTreeView;
233

    
234
    private SingleSelectionModel<Tag> tagTreeSelectionModel;
235
    private TagTreeViewModel tagTreeViewModel;
236
    private TagTreeView tagTreeView;
237

    
238
    private AccountResource account;
239

    
240
        @Override
241
        public void onModuleLoad() {
242
                if (parseUserCredentials())
243
            initialize();
244
        }
245

    
246
    private void initialize() {
247
        topPanel = new TopPanel(this, Pithos.images);
248
        topPanel.setWidth("100%");
249

    
250
        messagePanel.setWidth("100%");
251
        messagePanel.setVisible(false);
252

    
253

    
254
        // Inner contains the various lists.
255
        inner.sinkEvents(Event.ONCONTEXTMENU);
256
        inner.setAnimationEnabled(true);
257
        inner.getTabBar().addStyleName("pithos-MainTabBar");
258
        inner.getDeckPanel().addStyleName("pithos-MainTabPanelBottom");
259

    
260
        inner.setWidth("100%");
261

    
262
        inner.addSelectionHandler(new SelectionHandler<Integer>() {
263

    
264
            @Override
265
            public void onSelection(SelectionEvent<Integer> event) {
266
                int tabIndex = event.getSelectedItem();
267
                switch (tabIndex) {
268
                    case 0:
269
                        break;
270
                }
271
            }
272
        });
273

    
274
        folderTreeSelectionModel = new SingleSelectionModel<Folder>();
275
        folderTreeSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
276
            @Override
277
            public void onSelectionChange(SelectionChangeEvent event) {
278
                if (folderTreeSelectionModel.getSelectedObject() != null) {
279
                    tagTreeSelectionModel.setSelected(tagTreeSelectionModel.getSelectedObject(), false);
280
                    Folder f = folderTreeSelectionModel.getSelectedObject();
281
                    updateFolder(f, true);
282
                }
283
            }
284
        });
285

    
286
        folderTreeViewModel = new FolderTreeViewModel(this, folderTreeSelectionModel);
287
        folderTreeView = new FolderTreeView(folderTreeViewModel);
288

    
289
        fileList = new FileList(this, images, folderTreeView);
290
        inner.add(fileList, createHeaderHTML(AbstractImagePrototype.create(images.folders()), "Files"), true);
291

    
292
        tagTreeSelectionModel = new SingleSelectionModel<Tag>();
293
        tagTreeSelectionModel.addSelectionChangeHandler(new Handler() {
294
            @Override
295
            public void onSelectionChange(SelectionChangeEvent event) {
296
                if (tagTreeSelectionModel.getSelectedObject() != null) {
297
                    folderTreeSelectionModel.setSelected(folderTreeSelectionModel.getSelectedObject(), false);
298
                    Tag t = tagTreeSelectionModel.getSelectedObject();
299
                    updateTag(t);
300
                }
301
            }
302
        });
303
        tagTreeViewModel = new TagTreeViewModel(this, tagTreeSelectionModel);
304
        tagTreeView = new TagTreeView(tagTreeViewModel);
305

    
306
        VerticalPanel trees = new VerticalPanel();
307
        trees.add(folderTreeView);
308
        trees.add(tagTreeView);
309
        // Add the left and right panels to the split panel.
310
        splitPanel.setLeftWidget(trees);
311
        splitPanel.setRightWidget(inner);
312
        splitPanel.setSplitPosition("25%");
313
        splitPanel.setSize("100%", "100%");
314
        splitPanel.addStyleName("pithos-splitPanel");
315

    
316
        // Create a dock panel that will contain the menu bar at the top,
317
        // the shortcuts to the left, the status bar at the bottom and the
318
        // right panel taking the rest.
319
        VerticalPanel outer = new VerticalPanel();
320
        outer.add(topPanel);
321
        outer.add(messagePanel);
322
        outer.add(splitPanel);
323
        statusPanel = new StatusPanel();
324
        outer.add(statusPanel);
325
        outer.setWidth("100%");
326
        outer.setCellHorizontalAlignment(messagePanel, HasHorizontalAlignment.ALIGN_CENTER);
327

    
328
        // Hook the window resize event, so that we can adjust the UI.
329
        Window.addResizeHandler(this);
330
        // Clear out the window's built-in margin, because we want to take
331
        // advantage of the entire client area.
332
        Window.setMargin("0px");
333
        // Finally, add the outer panel to the RootPanel, so that it will be
334
        // displayed.
335
        RootPanel.get().add(outer);
336
        // Call the window resized handler to get the initial sizes setup. Doing
337
        // this in a deferred command causes it to occur after all widgets'
338
        // sizes have been computed by the browser.
339
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
340

    
341
            @Override
342
            public void execute() {
343
                onWindowResized(Window.getClientHeight());
344
            }
345
        });
346

    
347
        Scheduler.get().scheduleDeferred(new ScheduledCommand() {
348
            @Override
349
            public void execute() {
350
                fetchAccount();
351
            }
352
        });
353
    }
354

    
355
    public void showFiles(Folder f) {
356
        inner.selectTab(0);
357
        if (f.isTrash()) {
358
            fileList.showTrash();
359
        }
360
        else
361
            fileList.showFiles();
362
        Set<File> files = f.getFiles();
363
        showFiles(files);
364
    }
365

    
366
    public void showFiles(Set<File> files) {
367
        //Iterator<File> iter = files.iterator();
368
        //fetchFile(iter, files);
369
        fileList.setFiles(new ArrayList<File>(files));
370
    }
371

    
372
    private void fetchFile(final Iterator<File> iter, final Set<File> files) {
373
        if (iter.hasNext()) {
374
            File file = iter.next();
375
            String path = file.getUri() + "?format=json";
376
            GetRequest<File> getFile = new GetRequest<File>(File.class, getApiPath(), username, path, file) {
377
                @Override
378
                public void onSuccess(File result) {
379
                    fetchFile(iter, files);
380
                }
381

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

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

    
431
    /**
432
         * Redirect the user to the login page for authentication.
433
         */
434
        protected void authenticateUser() {
435
                Configuration conf = (Configuration) GWT.create(Configuration.class);
436
        Window.Location.assign(Window.Location.getHost() + conf.loginUrl() + "?next=" + Window.Location.getHref());
437
        }
438

    
439
    private void fetchAccount() {
440
        String path = "?format=json";
441

    
442
        GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, getApiPath(), username, path) {
443
            @Override
444
            public void onSuccess(AccountResource result) {
445
                account = result;
446
                inner.selectTab(0);
447
                if (account.getContainers().isEmpty())
448
                    createHomeContainers();
449
                else
450
                    folderTreeViewModel.initialize(account);
451
            }
452

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

    
466
    private void createHomeContainers() {
467
        String path = "/pithos";
468
        PutRequest createPithos = new PutRequest(getApiPath(), getUsername(), path) {
469
            @Override
470
            public void onSuccess(Resource result) {
471
                fetchAccount();
472
            }
473

    
474
            @Override
475
            public void onError(Throwable t) {
476
                GWT.log("Error creating pithos", t);
477
                if (t instanceof RestException)
478
                    displayError("Error creating pithos: " + ((RestException) t).getHttpStatusText());
479
                else
480
                    displayError("System error Error creating pithos: " + t.getMessage());
481
            }
482
        };
483
        createPithos.setHeader("X-Auth-Token", getToken());
484
        Scheduler.get().scheduleDeferred(createPithos);
485
    }
486

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

    
503
        private void onWindowResized(int height) {
504
                // Adjust the split panel to take up the available room in the window.
505
                int newHeight = height - splitPanel.getAbsoluteTop() - 60;
506
                if (newHeight < 1)
507
                        newHeight = 1;
508
                splitPanel.setHeight("" + newHeight);
509
                inner.setHeight("" + newHeight);
510
        }
511

    
512
        @Override
513
        public void onResize(ResizeEvent event) {
514
                int height = event.getHeight();
515
                onWindowResized(height);
516
        }
517

    
518
        /**
519
         * Display an error message.
520
         *
521
         * @param msg the message to display
522
         */
523
        public void displayError(String msg) {
524
                messagePanel.displayError(msg);
525
        }
526

    
527
        /**
528
         * Display a warning message.
529
         *
530
         * @param msg the message to display
531
         */
532
        public void displayWarning(String msg) {
533
                messagePanel.displayWarning(msg);
534
        }
535

    
536
        /**
537
         * Display an informational message.
538
         *
539
         * @param msg the message to display
540
         */
541
        public void displayInformation(String msg) {
542
                messagePanel.displayInformation(msg);
543
        }
544

    
545
        /**
546
         * Retrieve the fileList.
547
         *
548
         * @return the fileList
549
         */
550
        public FileList getFileList() {
551
                return fileList;
552
        }
553

    
554
        /**
555
         * Retrieve the topPanel.
556
         *
557
         * @return the topPanel
558
         */
559
        TopPanel getTopPanel() {
560
                return topPanel;
561
        }
562

    
563
        /**
564
         * Retrieve the clipboard.
565
         *
566
         * @return the clipboard
567
         */
568
        public Clipboard getClipboard() {
569
                return clipboard;
570
        }
571

    
572
        public StatusPanel getStatusPanel() {
573
                return statusPanel;
574
        }
575

    
576
        public String getToken() {
577
                return token;
578
        }
579

    
580
        public String getWebDAVPassword() {
581
                return webDAVPassword;
582
        }
583

    
584
        public static native void preventIESelection() /*-{
585
                $doc.body.onselectstart = function () { return false; };
586
        }-*/;
587

    
588
        public static native void enableIESelection() /*-{
589
                if ($doc.body.onselectstart != null)
590
                $doc.body.onselectstart = null;
591
        }-*/;
592

    
593
        /**
594
         * @return the absolute path of the API root URL
595
         */
596
        public String getApiPath() {
597
                Configuration conf = (Configuration) GWT.create(Configuration.class);
598
                return conf.apiPath();
599
        }
600

    
601
        /**
602
         * History support for folder navigation
603
         * adds a new browser history entry
604
         *
605
         * @param key
606
         */
607
        public void updateHistory(String key){
608
//                Replace any whitespace of the initial string to "+"
609
//                String result = key.replaceAll("\\s","+");
610
//                Add a new browser history entry.
611
//                History.newItem(result);
612
                History.newItem(key);
613
        }
614

    
615
    public void deleteFolder(final Folder folder) {
616
        String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + folder.getPrefix();
617
        RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
618
        builder.setHeader("If-Modified-Since", "0");
619
        builder.setHeader("X-Auth-Token", getToken());
620
        try {
621
            builder.sendRequest("", new RequestCallback() {
622
                @Override
623
                public void onResponseReceived(Request request, Response response) {
624
                    if (response.getStatusCode() == Response.SC_OK) {
625
                        JSONValue json = JSONParser.parseStrict(response.getText());
626
                        JSONArray array = json.isArray();
627
                        int i = 0;
628
                        if (array != null) {
629
                            deleteObject(folder, i, array);
630
                        }
631
                    }
632
                }
633

    
634
                @Override
635
                public void onError(Request request, Throwable exception) {
636
                    displayError("System error unable to delete folder: " + exception.getMessage());
637
                }
638
            });
639
        }
640
        catch (RequestException e) {
641
        }
642
    }
643

    
644
    public void deleteObject(final Folder folder, final int i, final JSONArray array) {
645
        if (i < array.size()) {
646
            JSONObject o = array.get(i).isObject();
647
            if (o != null && !o.containsKey("subdir")) {
648
                JSONString name = o.get("name").isString();
649
                String path = "/" + folder.getContainer() + "/" + name.stringValue();
650
                DeleteRequest delete = new DeleteRequest(getApiPath(), getUsername(), path) {
651
                    @Override
652
                    public void onSuccess(Resource result) {
653
                        deleteObject(folder, i + 1, array);
654
                    }
655

    
656
                    @Override
657
                    public void onError(Throwable t) {
658
                        GWT.log("", t);
659
                        displayError("System error unable to delete folder: " + t.getMessage());
660
                    }
661
                };
662
                delete.setHeader("X-Auth-Token", getToken());
663
                Scheduler.get().scheduleDeferred(delete);
664
            }
665
            else {
666
                String subdir = o.get("subdir").isString().stringValue();
667
                subdir = subdir.substring(0, subdir.length() - 1);
668
                String path = getApiPath() + getUsername() + "/" + folder.getContainer() + "?format=json&delimiter=/&prefix=" + subdir;
669
                RequestBuilder builder = new RequestBuilder(RequestBuilder.GET, path);
670
                builder.setHeader("If-Modified-Since", "0");
671
                builder.setHeader("X-Auth-Token", getToken());
672
                try {
673
                    builder.sendRequest("", new RequestCallback() {
674
                        @Override
675
                        public void onResponseReceived(Request request, Response response) {
676
                            if (response.getStatusCode() == Response.SC_OK) {
677
                                JSONValue json = JSONParser.parseStrict(response.getText());
678
                                JSONArray array2 = json.isArray();
679
                                if (array2 != null) {
680
                                    int l = array.size();
681
                                    for (int j=0; j<array2.size(); j++) {
682
                                        array.set(l++, array2.get(j));
683
                                    }
684
                                }
685
                                deleteObject(folder, i + 1, array);
686
                            }
687
                        }
688

    
689
                        @Override
690
                        public void onError(Request request, Throwable exception) {
691
                            displayError("System error unable to delete folder: " + exception.getMessage());
692
                        }
693
                    });
694
                }
695
                catch (RequestException e) {
696
                }
697
            }
698
        }
699
        else {
700
            String path = folder.getUri();
701
            DeleteRequest deleteFolder = new DeleteRequest(getApiPath(), getUsername(), path) {
702
                @Override
703
                public void onSuccess(Resource result) {
704
                    updateFolder(folder.getParent(), true);
705
                }
706

    
707
                @Override
708
                public void onError(Throwable t) {
709
                    GWT.log("", t);
710
                    if (t instanceof RestException) {
711
                        displayError("Unable to delete folder: "+((RestException) t).getHttpStatusText());
712
                    }
713
                    else
714
                        displayError("System error unable to delete folder: " + t.getMessage());
715
                }
716
            };
717
            deleteFolder.setHeader("X-Auth-Token", getToken());
718
            Scheduler.get().scheduleDeferred(deleteFolder);
719
        }
720
    }
721

    
722
    public FolderTreeView getFolderTreeView() {
723
        return folderTreeView;
724
    }
725

    
726
    public void copyFiles(final Iterator<File> iter, final String targetUri, final Command callback) {
727
        if (iter.hasNext()) {
728
            File file = iter.next();
729
            String path = targetUri + "/" + file.getName();
730
            PutRequest copyFile = new PutRequest(getApiPath(), getUsername(), path) {
731
                @Override
732
                public void onSuccess(Resource result) {
733
                    copyFiles(iter, targetUri, callback);
734
                }
735

    
736
                @Override
737
                public void onError(Throwable t) {
738
                    GWT.log("", t);
739
                    if (t instanceof RestException) {
740
                        displayError("Unable to copy file: " + ((RestException) t).getHttpStatusText());
741
                    }
742
                    else
743
                        displayError("System error unable to copy file: "+t.getMessage());
744
                }
745
            };
746
            copyFile.setHeader("X-Auth-Token", getToken());
747
            copyFile.setHeader("X-Copy-From", file.getUri());
748
            Scheduler.get().scheduleDeferred(copyFile);
749
        }
750
        else  if (callback != null) {
751
            callback.execute();
752
        }
753
    }
754

    
755
    public void copySubfolders(final Iterator<Folder> iter, final String targetUri, final Command callback) {
756
        if (iter.hasNext()) {
757
            final Folder f = iter.next();
758
            copyFolder(f, targetUri, callback);
759
        }
760
        else  if (callback != null) {
761
            callback.execute();
762
        }
763
    }
764

    
765
    public void copyFolder(final Folder f, final String targetUri, final Command callback) {
766
        String path = targetUri + "/" + f.getName();
767
        PutRequest createFolder = new PutRequest(getApiPath(), getUsername(), path) {
768
            @Override
769
            public void onSuccess(Resource result) {
770
                Iterator<File> iter = f.getFiles().iterator();
771
                copyFiles(iter, targetUri + "/" + f.getName(), new Command() {
772
                    @Override
773
                    public void execute() {
774
                        Iterator<Folder> iterf = f.getSubfolders().iterator();
775
                        copySubfolders(iterf, targetUri + "/" + f.getName(), new Command() {
776
                            @Override
777
                            public void execute() {
778
                                callback.execute();
779
                            }
780
                        });
781
                    }
782
                });
783
            }
784

    
785
            @Override
786
            public void onError(Throwable t) {
787
                GWT.log("", t);
788
                if (t instanceof RestException) {
789
                    displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());
790
                }
791
                else
792
                    displayError("System error creating folder:" + t.getMessage());
793
            }
794
        };
795
        createFolder.setHeader("X-Auth-Token", getToken());
796
        createFolder.setHeader("Accept", "*/*");
797
        createFolder.setHeader("Content-Length", "0");
798
        createFolder.setHeader("Content-Type", "application/folder");
799
        Scheduler.get().scheduleDeferred(createFolder);
800
    }
801
}