Statistics
| Branch: | Tag: | Revision:

root / src / gr / ebs / gss / client / FileUploadDialog.java @ 204107fb

History | View | Annotate | Download (15.5 kB)

1
/*
2
 * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.
3
 *
4
 * This file is part of GSS.
5
 *
6
 * GSS is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * GSS is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
package gr.ebs.gss.client;
20

    
21
import gr.ebs.gss.client.rest.GetCommand;
22
import gr.ebs.gss.client.rest.PostCommand;
23
import gr.ebs.gss.client.rest.RestCommand;
24
import gr.ebs.gss.client.rest.RestException;
25
import gr.ebs.gss.client.rest.resource.FileResource;
26
import gr.ebs.gss.client.rest.resource.FolderResource;
27
import gr.ebs.gss.client.rest.resource.UploadStatusResource;
28

    
29
import java.util.ArrayList;
30
import java.util.List;
31

    
32
import com.google.gwt.core.client.GWT;
33
import com.google.gwt.http.client.URL;
34
import com.google.gwt.json.client.JSONObject;
35
import com.google.gwt.json.client.JSONString;
36
import com.google.gwt.user.client.DeferredCommand;
37
import com.google.gwt.user.client.Timer;
38
import com.google.gwt.user.client.ui.Button;
39
import com.google.gwt.user.client.ui.ClickListener;
40
import com.google.gwt.user.client.ui.DialogBox;
41
import com.google.gwt.user.client.ui.FileUpload;
42
import com.google.gwt.user.client.ui.FormHandler;
43
import com.google.gwt.user.client.ui.FormPanel;
44
import com.google.gwt.user.client.ui.FormSubmitCompleteEvent;
45
import com.google.gwt.user.client.ui.FormSubmitEvent;
46
import com.google.gwt.user.client.ui.Grid;
47
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
48
import com.google.gwt.user.client.ui.Hidden;
49
import com.google.gwt.user.client.ui.HorizontalPanel;
50
import com.google.gwt.user.client.ui.KeyboardListener;
51
import com.google.gwt.user.client.ui.Label;
52
import com.google.gwt.user.client.ui.VerticalPanel;
53
import com.google.gwt.user.client.ui.Widget;
54

    
55
/**
56
 * The 'File upload' dialog box implementation.
57
 */
58
public class FileUploadDialog extends DialogBox implements Updateable {
59

    
60
        protected int prgBarInterval = 1500;
61

    
62
        protected ProgressBar progressBar;
63

    
64
        protected RepeatingTimer repeater = new RepeatingTimer(this, prgBarInterval);
65

    
66
        public static final boolean DONE = true;
67

    
68
        /**
69
         * The Form element that performs the file upload.
70
         */
71
        private final FormPanel form = new FormPanel();
72

    
73
        private final FileUpload upload = new FileUpload();
74

    
75
        protected final Label filenameLabel = new Label("");
76

    
77
        protected List<FileResource> files;
78

    
79
        protected boolean cancelEvent = false;
80

    
81
        protected String fileNameToUse;
82

    
83
        protected FolderResource folder;
84

    
85
        /**
86
         * The widget's constructor.
87
         */
88
        public FileUploadDialog() {
89
                // Set the dialog's caption.
90
                setText("File upload");
91
                setAnimationEnabled(true);
92
                // Since we're going to add a FileUpload widget, we'll need to set the
93
                // form to use the POST method, and multipart MIME encoding.
94
                form.setEncoding(FormPanel.ENCODING_MULTIPART);
95
                form.setMethod(FormPanel.METHOD_POST);
96

    
97
                // Create a panel to hold all of the form widgets.
98
                VerticalPanel panel = new VerticalPanel();
99
                form.setWidget(panel);
100
                final Hidden date = new Hidden("Date", "");
101
                panel.add(date);
102
                final Hidden auth = new Hidden("Authorization", "");
103
                panel.add(auth);
104
                // Add an informative label with the folder name.
105
                Object selection = GSS.get().getFolders().getCurrent().getUserObject();
106
                folder = (FolderResource) selection;
107
                upload.setName("file");
108
                filenameLabel.setText("");
109
                filenameLabel.setVisible(false);
110
                filenameLabel.setStyleName("props-labels");
111
                HorizontalPanel fileUloadPanel = new HorizontalPanel();
112
                fileUloadPanel.add(filenameLabel);
113
                fileUloadPanel.add(upload);
114
                Grid generalTable = new Grid(2, 2);
115
                generalTable.setText(0, 0, "Folder");
116
                generalTable.setText(1, 0, "File");
117
                generalTable.setText(0, 1, folder.getName());
118
                generalTable.setWidget(1, 1, fileUloadPanel);
119
                generalTable.getCellFormatter().setStyleName(0, 0, "props-labels");
120
                generalTable.getCellFormatter().setStyleName(1, 0, "props-labels");
121
                generalTable.getCellFormatter().setStyleName(0, 1, "props-values");
122
                generalTable.getCellFormatter().setStyleName(1, 1, "props-values");
123
                generalTable.setCellSpacing(4);
124

    
125
                panel.add(generalTable);
126

    
127
                // Create a panel to hold the buttons.
128
                HorizontalPanel buttons = new HorizontalPanel();
129

    
130
                // Create the 'upload' button, along with a listener that submits the
131
                // form.
132
                final Button submit = new Button("Upload", new ClickListener() {
133
                        public void onClick(Widget sender) {
134
                                prepareAndSubmit();
135
                        }
136
                });
137
                buttons.add(submit);
138
                buttons.setCellHorizontalAlignment(submit, HasHorizontalAlignment.ALIGN_CENTER);
139
                // Create the 'Cancel' button, along with a listener that hides the
140
                // dialog when the button is clicked.
141
                final Button cancel = new Button("Cancel", new ClickListener() {
142

    
143
                        public void onClick(Widget sender) {
144
                                repeater.finish();
145
                                hide();
146
                        }
147
                });
148
                buttons.add(cancel);
149
                buttons.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);
150
                buttons.setSpacing(8);
151
                buttons.addStyleName("gss-DialogBox");
152

    
153
                // Add an event handler to the form.
154
                form.addFormHandler(new FormHandler() {
155

    
156
                        public void onSubmit(final FormSubmitEvent event) {
157
                                GSS app = GSS.get();
158
                                // This event is fired just before the form is submitted. We can
159
                                // take this opportunity to perform validation.
160
                                if (upload.getFilename().length() == 0) {
161
                                        app.displayError("You must select a file!");
162
                                        event.setCancelled(true);
163
                                        hide();
164
                                } else {
165

    
166
                                        canContinue();
167
                                        GWT.log("Cancel:" + cancelEvent, null);
168
                                        if (cancelEvent) {
169
                                                cancelEvent = false;
170
                                                app.displayError("The specified file name already exists in this folder");
171
                                                event.setCancelled(true);
172
                                                hide();
173
                                        } else {
174

    
175
                                                fileNameToUse = getFilename(upload.getFilename());
176
                                                String apath;
177
                                                FileResource selectedFile = getFileForName(fileNameToUse);
178
                                                if (selectedFile == null ) {
179
                                                        //we are going to create a file
180
                                                        apath = folder.getUri();
181
                                                        if (!apath.endsWith("/"))
182
                                                                apath = apath + "/";
183
                                                        apath = apath + encodeComponent(fileNameToUse);
184
                                                } else
185
                                                        apath = selectedFile.getUri();
186
                                                form.setAction(apath);
187
                                                String dateString = RestCommand.getDate();
188
                                                String resource = apath.substring(app.getApiPath().length() - 1, apath.length());
189
                                                String sig = RestCommand.calculateSig("POST", dateString, resource, RestCommand.base64decode(app.getToken()));
190
                                                date.setValue(dateString);
191
                                                auth.setValue(app.getCurrentUserResource().getUsername() + " " + sig);
192
                                                GWT.log("FolderPATH:" + folder.getUri(), null);
193
                                                submit.setEnabled(false);
194
                                                upload.setVisible(false);
195
                                                filenameLabel.setText(fileNameToUse);
196
                                                filenameLabel.setVisible(true);
197
                                                repeater.start();
198
                                                progressBar.setVisible(true);
199
                                        }
200
                                }
201
                        }
202

    
203
                        public void onSubmitComplete(final FormSubmitCompleteEvent event) {
204
                                // When the form submission is successfully completed, this
205
                                // event is fired. Assuming the service returned a response
206
                                // of type text/html, we can get the result text here (see
207
                                // the FormPanel documentation for further explanation).
208
                                String results = event.getResults();
209

    
210
                                // Unfortunately the results are never empty, even in
211
                                // the absense of errors, so we have to check for '<pre></pre>'.
212
                                if (!results.equalsIgnoreCase("<pre></pre>")) {
213
                                        GWT.log(results, null);
214
                                        GSS.get().displayError(results);
215
                                }
216
                                progressBar.setProgress(100);
217
                                repeater.finish();
218
                                hide();
219
                                GSS.get().showFileList(true);
220
                                GSS.get().getStatusPanel().updateStats();
221
                        }
222
                });
223

    
224
                panel.add(buttons);
225
                progressBar = new ProgressBar(50, ProgressBar.SHOW_TIME_REMAINING);
226
                panel.add(progressBar);
227
                progressBar.setVisible(false);
228
                panel.setCellHorizontalAlignment(buttons, HasHorizontalAlignment.ALIGN_CENTER);
229
                panel.setCellHorizontalAlignment(progressBar, HasHorizontalAlignment.ALIGN_CENTER);
230
                panel.addStyleName("gss-DialogBox");
231
                addStyleName("gss-DialogBox");
232
                setWidget(form);
233
        }
234

    
235
        @Override
236
        public boolean onKeyDownPreview(char key, int modifiers) {
237
                // Use the popup's key preview hooks to close the dialog when either
238
                // enter or escape is pressed.
239
                switch (key) {
240
                        case KeyboardListener.KEY_ENTER:
241
                                prepareAndSubmit();
242
                                break;
243
                        case KeyboardListener.KEY_ESCAPE:
244
                                repeater.finish();
245
                                hide();
246
                                break;
247
                }
248

    
249
                return true;
250
        }
251

    
252
        public void prepareAndSubmit() {
253
                final String fname = getFilename(upload.getFilename());
254
                if (getFileForName(fname) == null) {
255
                        //we are going to create a file, so we check to see if there is a trashed file with the same name
256
                        FileResource same = null;
257
                        for (FileResource fres : folder.getFiles())
258
                                if (fres.isDeleted() && fres.getName().equals(fname))
259
                                        same = fres;
260
                        if (same == null)
261
                                form.submit();
262
                        else {
263
                                final FileResource sameFile = same;
264
                                GWT.log("Same deleted file", null);
265
                                ConfirmationDialog confirm = new ConfirmationDialog("A file with " +
266
                                                "the same name exists in the trash. If you continue,<br/>the trashed " +
267
                                                "file  '" + fname + "' will be renamed automatically for you.", "Continue") {
268

    
269
                                        @Override
270
                                        public void cancel() {
271
                                                FileUploadDialog.this.hide();
272
                                        }
273

    
274
                                        @Override
275
                                        public void confirm() {
276
                                                updateTrashedFile(getBackupFilename(fname), sameFile);
277
                                        }
278

    
279
                                };
280
                                confirm.center();
281
                        }
282
                }
283
                else {
284
                        // We are going to update an existing file, so show a confirmation dialog.
285
                        ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " +
286
                                        "you want to update " + fname + "?", "Update") {
287

    
288
                                @Override
289
                                public void cancel() {
290
                                        FileUploadDialog.this.hide();
291
                                }
292

    
293
                                @Override
294
                                public void confirm() {
295
                                        form.submit();
296
                                }
297

    
298
                        };
299
                        confirm.center();
300
                }
301
        }
302

    
303
        /**
304
         * Returns the file name from a potential full path argument. Apparently IE
305
         * insists on sending the full path name of a file when uploading, forcing
306
         * us to trim the extra path info. Since this is only observed on Windows we
307
         * get to check for a single path separator value.
308
         *
309
         * @param name the potentially full path name of a file
310
         * @return the file name without extra path information
311
         */
312
        protected String getFilename(String name) {
313
                int pathSepIndex = name.lastIndexOf("\\");
314
                if (pathSepIndex == -1) {
315
                        pathSepIndex = name.lastIndexOf("/");
316
                        if (pathSepIndex == -1)
317
                                return name;
318
                }
319
                return name.substring(pathSepIndex + 1);
320
        }
321

    
322
        /**
323
         * Check whether the file name exists in selected folder.
324
         *
325
         * @return
326
         */
327
        private boolean canContinue() {
328
                if (files == null)
329
                        return false;
330
                String fileName = getFilename(upload.getFilename());
331
                if (getFileForName(fileName) == null) {
332
                        // For file creation, check to see if the file already exists.
333
                        GWT.log("filename to upload:" + fileName, null);
334
                        for (FileResource dto : files) {
335
                                GWT.log("Check:" + dto.getName() + "/" + fileName, null);
336
                                if (!dto.isDeleted() && dto.getName().equals(fileName)) {
337
                                        cancelEvent = true;
338
                                        return true;
339
                                }
340
                        }
341
                }
342
                return true;
343
        }
344

    
345
        class RepeatingTimer extends Timer {
346

    
347
                private Updateable updateable;
348

    
349
                private int interval = 1500;
350

    
351
                private boolean running = true;
352

    
353
                RepeatingTimer(Updateable _updateable, int _interval) {
354
                        updateable = _updateable;
355
                        interval = _interval;
356
                }
357

    
358
                @Override
359
                public void run() {
360
                        updateable.update();
361
                }
362

    
363
                public void start() {
364
                        running = true;
365

    
366
                        scheduleRepeating(interval);
367
                }
368

    
369
                public void finish() {
370
                        running = false;
371
                        cancel();
372
                }
373

    
374
                public int getInterval() {
375
                        return interval;
376
                }
377

    
378
                public void setInterval(int anInterval) {
379
                        if (interval != anInterval) {
380
                                interval = anInterval;
381
                                if (running) {
382
                                        finish();
383
                                        start();
384
                                }
385
                        }
386
                }
387
        }
388

    
389
        /* (non-Javadoc)
390
         * @see gr.ebs.gss.client.Updateable#update()
391
         */
392
        public void update() {
393
                String apath = folder.getUri();
394
                if (!apath.endsWith("/"))
395
                        apath = apath + "/";
396
                apath = apath + encodeComponent(fileNameToUse) + "?progress=" + encodeComponent(fileNameToUse);
397
                GetCommand eg = new GetCommand<UploadStatusResource>(UploadStatusResource.class, apath, false) {
398

    
399
                        @Override
400
                        public void onComplete() {
401
                                UploadStatusResource res = getResult();
402
                                progressBar.setProgress(res.percent());
403
                        }
404

    
405
                        @Override
406
                        public void onError(Throwable t) {
407
                                GWT.log("", t);
408
                        }
409

    
410
                };
411
                DeferredCommand.addCommand(eg);
412
        }
413

    
414
        protected String getBackupFilename(String filename) {
415
                List<FileResource> filesInSameFolder = new ArrayList<FileResource>();
416
                for (FileResource deleted : folder.getFiles())
417
                        if (deleted.isDeleted())
418
                                filesInSameFolder.add(deleted);
419
                int i = 1;
420
                for (FileResource same : filesInSameFolder)
421
                        if (same.getName().startsWith(filename)) {
422
                                String toCheck = same.getName().substring(filename.length(), same.getName().length());
423
                                if (toCheck.startsWith(" ")) {
424
                                        int test = -1;
425
                                        try {
426
                                                test = Integer.valueOf(toCheck.replace(" ", ""));
427
                                        } catch (NumberFormatException e) {
428
                                                // Do nothing since string is not a number.
429
                                        }
430
                                        if (test >= i)
431
                                                i = test + 1;
432
                                }
433
                        }
434

    
435
                return filename + " " + i;
436
        }
437

    
438
        private void updateTrashedFile(String newName, FileResource trashedFile) {
439
                JSONObject json = new JSONObject();
440
                json.put("name", new JSONString(newName));
441
                PostCommand cf = new PostCommand(trashedFile.getUri() + "?update=", json.toString(), 200) {
442

    
443
                        @Override
444
                        public void onComplete() {
445
                                form.submit();
446
                        }
447

    
448
                        @Override
449
                        public void onError(Throwable t) {
450
                                GWT.log("", t);
451
                                if (t instanceof RestException) {
452
                                        int statusCode = ((RestException) t).getHttpStatusCode();
453
                                        if (statusCode == 405)
454
                                                GSS.get().displayError("You don't have the necessary permissions");
455
                                        else if (statusCode == 404)
456
                                                GSS.get().displayError("User in permissions does not exist");
457
                                        else if (statusCode == 409)
458
                                                GSS.get().displayError("A file with the same name already exists");
459
                                        else if (statusCode == 413)
460
                                                GSS.get().displayError("Your quota has been exceeded");
461
                                        else
462
                                                GSS.get().displayError("Unable to modify file:" +((RestException)t).getHttpStatusText());
463
                                } else
464
                                        GSS.get().displayError("System error modifying file:" + t.getMessage());
465
                        }
466

    
467
                };
468
                DeferredCommand.addCommand(cf);
469
        }
470

    
471
        protected FileResource getFileForName(String name){
472
                for (FileResource f : folder.getFiles())
473
                        if (!f.isDeleted() && f.getName().equals(name))
474
                                return f;
475
                return null;
476
        }
477

    
478

    
479
        /**
480
         * Same as URL.encodeComponent, but also
481
         * encode apostrophe since browsers aren't consistent about it
482
         * (FF encodes, IE does not).
483
         *
484
         * @param decodedURLComponent
485
         * @return
486
         */
487
        protected String encodeComponent(String decodedURLComponent) {
488
                String retv = URL.encodeComponent(decodedURLComponent);
489
                retv = retv.replaceAll("'", "%27");
490
                return retv;
491
        }
492

    
493
        /**
494
         * Modify the files.
495
         *
496
         * @param newFiles the files to set
497
         */
498
        public void setFiles(List<FileResource> newFiles) {
499
                files = newFiles;
500
        }
501
}