abae4daf2e5bfb92fd0b66e9c47cdaf2b1cfe22c
[pithos-web-client] / src / gr / grnet / pithos / web / client / FileUploadDialog.java
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.foldertree.File;
38 import gr.grnet.pithos.web.client.foldertree.Folder;
39
40 import com.google.gwt.core.client.Scheduler;
41 import com.google.gwt.event.dom.client.ClickEvent;
42 import com.google.gwt.event.dom.client.ClickHandler;
43 import com.google.gwt.user.client.Command;
44 import com.google.gwt.user.client.ui.Anchor;
45 import com.google.gwt.user.client.ui.Button;
46 import com.google.gwt.user.client.ui.DialogBox;
47 import com.google.gwt.user.client.ui.FileUpload;
48 import com.google.gwt.user.client.ui.FlowPanel;
49 import com.google.gwt.user.client.ui.FormPanel;
50 import com.google.gwt.user.client.ui.Grid;
51 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
52 import com.google.gwt.user.client.ui.Hidden;
53 import com.google.gwt.user.client.ui.HorizontalPanel;
54 import com.google.gwt.user.client.ui.Label;
55 import com.google.gwt.user.client.ui.VerticalPanel;
56
57 /**
58  * The 'File upload' dialog box implementation.
59  */
60 public class FileUploadDialog extends DialogBox {
61
62     public static final boolean DONE = true;
63
64         /**
65          * The Form element that performs the file upload.
66          */
67     protected final FormPanel form = new FormPanel();
68
69         private final FileUpload upload = new FileUpload();
70
71         private final Label filenameLabel = new Label();
72
73     private final Label foldernameLabel = new Label();
74
75     private Button submit;
76
77         protected Folder folder;
78
79     protected Pithos app;
80
81         /**
82          * The widget's constructor.
83          */
84         public FileUploadDialog(Pithos _app, Folder _folder) {
85                 app = _app;
86                 folder = _folder;
87                 foldernameLabel.setText(folder.getName());
88                 Anchor close = new Anchor();
89                 close.addStyleName("close");
90                 close.addClickHandler(new ClickHandler() {
91                         
92                         @Override
93                         public void onClick(ClickEvent event) {
94                                 hide();
95                         }
96                 });
97                 // Set the dialog's caption.
98                 setText("File upload");
99                 setAnimationEnabled(true);
100                 setGlassEnabled(true);
101                 setStyleName("pithos-DialogBox");
102                 // Since we're going to add a FileUpload widget, we'll need to set the
103                 // form to use the POST method, and multipart MIME encoding.
104                 form.setEncoding(FormPanel.ENCODING_MULTIPART);
105                 form.setMethod(FormPanel.METHOD_POST);
106
107                 // Create a panel to hold all of the form widgets.
108                 VerticalPanel panel = new VerticalPanel();
109                 panel.add(close);
110                 form.setWidget(panel);
111
112                 VerticalPanel inner = new VerticalPanel();
113                 inner.addStyleName("inner");
114
115         final Hidden auth = new Hidden("X-Auth-Token");
116         inner.add(auth);
117                 upload.setName("X-Object-Data");
118                 upload.setVisible(false);
119                 filenameLabel.setText("");
120                 filenameLabel.setVisible(false);
121                 filenameLabel.setStyleName("props-labels");
122                 HorizontalPanel fileUploadPanel = new HorizontalPanel();
123                 fileUploadPanel.setVisible(false);
124                 fileUploadPanel.add(filenameLabel);
125                 fileUploadPanel.add(upload);
126                 Grid generalTable = new Grid(2, 2);
127                 generalTable.setText(0, 0, "Folder");
128         generalTable.setWidget(0, 1, foldernameLabel);
129                 generalTable.setWidget(1, 1, fileUploadPanel);
130                 generalTable.getCellFormatter().setStyleName(0, 0, "props-labels");
131         generalTable.getCellFormatter().setStyleName(0, 1, "props-values");
132         generalTable.getCellFormatter().setVisible(1, 0, false);
133                 generalTable.setCellSpacing(4);
134
135                 inner.add(generalTable);
136
137                 FlowPanel uploader = new FlowPanel();
138                 uploader.getElement().setId("uploader");
139                 inner.add(uploader);
140                 
141                 panel.add(inner);
142                 panel.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
143                 
144                 
145                 Scheduler.get().scheduleDeferred(new Command() {
146                         
147                         @Override
148                         public void execute() {
149                                 String path = app.getApiPath() + folder.getOwner() + folder.getUri();
150                                 setupUpload(FileUploadDialog.this, path, app.getToken());
151                         }
152                 });
153                 setWidget(form);
154         }
155
156         private void refreshFolder() {
157                 if (app.getSelectedTree().equals(app.getFolderTreeView()))
158                         app.updateFolder(folder, true, new Command() {
159                                 
160                                 @Override
161                                 public void execute() {
162                                         app.updateStatistics();
163                                 }
164                         });
165                 else
166                         app.updateOtherSharedFolder(folder, true);
167         }
168         
169         native void setupUpload(FileUploadDialog dlg, String path, String token) /*-{
170                 $wnd.$("#uploader").pluploadQueue({
171                         // General settings
172                         runtimes : 'html5, silverlight, flash, gears, browserplus, html4',
173                         unique_names : true,
174         
175                         // Flash settings
176                         flash_swf_url : 'plupload/js/plupload.flash.swf',
177         
178                         // Silverlight settings
179                         silverlight_xap_url : 'plupload/js/plupload.silverlight.xap',
180                         
181                         preinit: {
182                                 Init: function(up, info) {
183                                         up.settings.file_data_name = "X-Object-Data";                           
184                                 },
185                                 
186                                 UploadFile: function(up, file) {
187                                         $wnd.console.log('About to upload ' + file.name);
188                                         up.settings.url = path + "/" + file.name + "?X-Auth-Token=" + token;
189                                 }
190                         },
191                         
192                         init: {
193                                 FileUploaded: function(up, file, response) {
194                                         $wnd.console.log('File ' + file.name + ' uploaded');
195                                         $wnd.console.log('Response: ' + response);
196                                 },
197                                 
198                                 UploadComplete: function(up, files) {
199                                         $wnd.console.log('All files finished');
200                                         dlg.@gr.grnet.pithos.web.client.FileUploadDialog::refreshFolder()();
201                                 }
202                         }
203                 });
204         
205                 // Client side form validation
206                 $wnd.$('form').submit(function(e) {
207                 var uploader = $wnd.$('#uploader').pluploadQueue();
208         
209                 // Files in queue upload them first
210                 if (uploader.files.length > 0) {
211                     // When all files are uploaded submit form
212                     uploader.bind('StateChanged', function() {
213                         if (uploader.files.length === (uploader.total.uploaded + uploader.total.failed)) {
214                             $wnd.$('form')[0].submit();
215                         }
216                     });
217                         
218                     uploader.start();
219                 } else {
220                     alert('You must queue at least one file.');
221                 }
222         
223                 return false;
224             });
225         }-*/;
226         
227         /**
228          * Make any last minute checks and start the upload.
229          */
230         protected void prepareAndSubmit() {
231         if (upload.getFilename().length() == 0) {
232             app.displayError("You must select a file!");
233             return;
234         }
235         final String fname = getFilename(upload.getFilename());
236         String apath = app.getApiPath() + folder.getOwner() + folder.getUri() + "/" + fname + "?X-Auth-Token=" + app.getToken();
237         form.setAction(apath);
238         submit.setEnabled(false);
239         upload.setVisible(false);
240         filenameLabel.setText(fname);
241         filenameLabel.setVisible(true);
242
243                 if (getFileForName(fname) == null) {
244             form.submit();
245                 }
246                 else {
247                         // We are going to update an existing file, so show a confirmation dialog.
248                         ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " +
249                                         "you want to update " + fname + "?", "Update") {
250
251                                 @Override
252                                 public void cancel() {
253                                         FileUploadDialog.this.hide();
254                                 }
255
256                                 @Override
257                                 public void confirm() {
258                                         form.submit();
259                                 }
260
261                         };
262                         confirm.center();
263                 }
264         }
265
266     /**
267          * Returns the file name from a potential full path argument. Apparently IE
268          * insists on sending the full path name of a file when uploading, forcing
269          * us to trim the extra path info. Since this is only observed on Windows we
270          * get to check for a single path separator value.
271          *
272          * @param name the potentially full path name of a file
273          * @return the file name without extra path information
274          */
275         protected String getFilename(String name) {
276                 int pathSepIndex = name.lastIndexOf("\\");
277                 if (pathSepIndex == -1) {
278                         pathSepIndex = name.lastIndexOf("/");
279                         if (pathSepIndex == -1)
280                                 return name;
281                 }
282                 return name.substring(pathSepIndex + 1);
283         }
284
285         protected File getFileForName(String name){
286                 for (File f : folder.getFiles())
287                         if (f.getName().equals(name))
288                                 return f;
289                 return null;
290         }
291 }