Added two new classes. The first 'TestFolderSharing' handles the 'Sharing' option...
[pithos] / src / gr / ebs / gss / client / FileUploadGearsDialog.java
index fad3190..ef5b0f1 100644 (file)
-/*\r
- * Copyright 2009 Electronic Business Systems Ltd.\r
- *\r
- * This file is part of GSS.\r
- *\r
- * GSS is free software: you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation, either version 3 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * GSS is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with GSS.  If not, see <http://www.gnu.org/licenses/>.\r
- */\r
-package gr.ebs.gss.client;\r
-\r
-import gr.ebs.gss.client.rest.PostCommand;\r
-import gr.ebs.gss.client.rest.RestCommand;\r
-import gr.ebs.gss.client.rest.RestException;\r
-import gr.ebs.gss.client.rest.resource.FileResource;\r
-import gr.ebs.gss.client.rest.resource.FolderResource;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.List;\r
-\r
-import com.google.gwt.core.client.GWT;\r
-import com.google.gwt.gears.client.Factory;\r
-import com.google.gwt.gears.client.desktop.Desktop;\r
-import com.google.gwt.gears.client.desktop.File;\r
-import com.google.gwt.gears.client.desktop.OpenFilesHandler;\r
-import com.google.gwt.gears.client.httprequest.HttpRequest;\r
-import com.google.gwt.gears.client.httprequest.ProgressEvent;\r
-import com.google.gwt.gears.client.httprequest.ProgressHandler;\r
-import com.google.gwt.gears.client.httprequest.RequestCallback;\r
-import com.google.gwt.json.client.JSONObject;\r
-import com.google.gwt.json.client.JSONString;\r
-import com.google.gwt.user.client.Command;\r
-import com.google.gwt.user.client.DeferredCommand;\r
-import com.google.gwt.user.client.ui.Button;\r
-import com.google.gwt.user.client.ui.ClickListener;\r
-import com.google.gwt.user.client.ui.FlexTable;\r
-import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
-import com.google.gwt.user.client.ui.HorizontalPanel;\r
-import com.google.gwt.user.client.ui.VerticalPanel;\r
-import com.google.gwt.user.client.ui.Widget;\r
-\r
-/**\r
- * The 'File upload' dialog box implementation with Google Gears support.\r
- */\r
-public class FileUploadGearsDialog extends FileUploadDialog implements Updateable {\r
-\r
-       private final Factory factory = Factory.getInstance();\r
-\r
-       /**\r
-        * The array of files to upload.\r
-        */\r
-       private File[] fileObjects;\r
-\r
-       /**\r
-        * A list of files to upload, created from files array. Used to signal\r
-        * finished state when empty.\r
-        */\r
-       private List<File> selectedFiles = new ArrayList<File>();\r
-\r
-       /**\r
-        * The list of progress bars for individual files.\r
-        */\r
-       private List<ProgressBar> progressBars = new ArrayList<ProgressBar>();\r
-\r
-       private Button browse;\r
-\r
-       private Button submit;\r
-\r
-       private FlexTable generalTable;\r
-\r
-       /**\r
-        * The widget's constructor.\r
-        */\r
-       public FileUploadGearsDialog() {\r
-               // Set the dialog's caption.\r
-               setText("File upload");\r
-               setAnimationEnabled(true);\r
-               // Create a panel to hold all of the dialog widgets.\r
-               VerticalPanel panel = new VerticalPanel();\r
-               // Add an informative label with the folder name.\r
-               Object selection = GSS.get().getFolders().getCurrent().getUserObject();\r
-               folder = (FolderResource) selection;\r
-\r
-               browse = new Button("Browse...");\r
-\r
-               HorizontalPanel fileUploadPanel = new HorizontalPanel();\r
-               fileUploadPanel.add(browse);\r
-\r
-               generalTable = new FlexTable();\r
-               generalTable.setText(0, 0, "Folder");\r
-               generalTable.setText(1, 0, "File");\r
-               generalTable.setText(0, 1, folder.getName());\r
-               generalTable.setWidget(1, 1, fileUploadPanel);\r
-               generalTable.getCellFormatter().setStyleName(0, 0, "props-labels");\r
-               generalTable.getCellFormatter().setStyleName(1, 0, "props-labels");\r
-               generalTable.getCellFormatter().setStyleName(0, 1, "props-values");\r
-               generalTable.getCellFormatter().setStyleName(1, 1, "props-values");\r
-               generalTable.setCellSpacing(4);\r
-\r
-               panel.add(generalTable);\r
-\r
-               // Create a panel to hold the buttons.\r
-               HorizontalPanel buttons = new HorizontalPanel();\r
-\r
-               submit = new Button("Upload");\r
-               submit.addClickListener(new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               prepareAndSubmit();\r
-                       }\r
-               });\r
-               submit.setEnabled(false);\r
-               buttons.add(submit);\r
-               buttons.setCellHorizontalAlignment(submit, HasHorizontalAlignment.ALIGN_CENTER);\r
-               // Create the 'Cancel' button, along with a listener that hides the\r
-               // dialog when the button is clicked.\r
-               Button cancel = new Button("Cancel", new ClickListener() {\r
-\r
-                       public void onClick(Widget sender) {\r
-                               hide();\r
-                       }\r
-               });\r
-               buttons.add(cancel);\r
-               buttons.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);\r
-               buttons.setSpacing(8);\r
-               buttons.addStyleName("gss-DialogBox");\r
-\r
-               browse.addClickListener(new ClickListener() {\r
-                       public void onClick(Widget sender) {\r
-                               Desktop desktop = factory.createDesktop();\r
-                               desktop.openFiles(new OpenFilesHandler() {\r
-\r
-                                       public void onOpenFiles(OpenFilesEvent event) {\r
-                                               fileObjects = event.getFiles();\r
-                                               selectedFiles.addAll(Arrays.asList(fileObjects));\r
-                                               for (int i = 0; i< selectedFiles.size(); i++) {\r
-                                                       generalTable.setText(i+1, 0, "File");\r
-                                                       generalTable.setText(i+1, 1, selectedFiles.get(i).getName());\r
-                                                       ProgressBar progress = new ProgressBar(20, 0);\r
-                                                       generalTable.setWidget(i+1, 2, progress);\r
-                                                       progressBars.add(progress);\r
-                                                       generalTable.getCellFormatter().setStyleName(i+1, 0, "props-labels");\r
-                                                       generalTable.getCellFormatter().setStyleName(i+1, 1, "props-values");\r
-                                               }\r
-                                               submit.setEnabled(true);\r
-                                       }\r
-                               });\r
-                       }\r
-               });\r
-\r
-               panel.add(buttons);\r
-               panel.setCellHorizontalAlignment(buttons, HasHorizontalAlignment.ALIGN_CENTER);\r
-               panel.addStyleName("gss-DialogBox");\r
-               addStyleName("gss-DialogBox");\r
-               setWidget(panel);\r
-       }\r
-\r
-       /**\r
-        * Check whether the specified file name exists in the selected folder.\r
-        */\r
-       private boolean canContinue(File file) {\r
-               String fileName = getFilename(file.getName());\r
-               if (getFileForName(fileName) == null)\r
-                       // For file creation, check to see if the file already exists.\r
-                       for (FileResource fileRes : files)\r
-                               if (!fileRes.isDeleted() && fileRes.getName().equals(fileName))\r
-                                       return false;\r
-               return true;\r
-       }\r
-\r
-       @Override\r
-       public void prepareAndSubmit() {\r
-               GSS app = GSS.get();\r
-               if (selectedFiles.size() == 0) {\r
-                       app.displayError("You must select a file!");\r
-                       hide();\r
-                       return;\r
-               }\r
-               for(File file: selectedFiles)\r
-                       if (!canContinue(file)) {\r
-                               app.displayError("The file name " + file.getName() +\r
-                                                       " already exists in this folder");\r
-                               hide();\r
-                               return;\r
-                       }\r
-               submit.setEnabled(false);\r
-               browse.setVisible(false);\r
-               final String fname = getFilename(selectedFiles.get(0).getName());\r
-               if (getFileForName(fname) == null) {\r
-                       // We are going to create a file, so we check to see if there is a\r
-                       // trashed file with the same name.\r
-                       FileResource same = null;\r
-                       for (FileResource fres : folder.getFiles())\r
-                               if (fres.isDeleted() && fres.getName().equals(fname))\r
-                                       same = fres;\r
-                       if (same == null)\r
-                               uploadFiles();\r
-                       else {\r
-                               final FileResource sameFile = same;\r
-                               GWT.log("Same deleted file", null);\r
-                               ConfirmationDialog confirm = new ConfirmationDialog("A file " +\r
-                                               "with the same name exists in the trash. If you " +\r
-                                               "continue,<br/>the trashed file  '" + fname +\r
-                                               "' will be renamed automatically for you.", "Continue") {\r
-\r
-                                       @Override\r
-                                       public void cancel() {\r
-                                               hide();\r
-                                       }\r
-\r
-                                       @Override\r
-                                       public void confirm() {\r
-                                               updateTrashedFile(getBackupFilename(fname), sameFile);\r
-                                       }\r
-\r
-                               };\r
-                               confirm.center();\r
-                       }\r
-               } else {\r
-                       // We are going to update an existing file, so show a confirmation dialog.\r
-                       ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " +\r
-                                       "you want to update " + fname + "?", "Update"){\r
-\r
-                               @Override\r
-                               public void cancel() {\r
-                                       hide();\r
-                               }\r
-\r
-                               @Override\r
-                               public void confirm() {\r
-                                       uploadFiles();\r
-                               }\r
-\r
-                       };\r
-                       confirm.center();\r
-               }\r
-       }\r
-\r
-       private void updateTrashedFile(String newName, FileResource trashedFile) {\r
-               JSONObject json = new JSONObject();\r
-               json.put("name", new JSONString(newName));\r
-               PostCommand cf = new PostCommand(trashedFile.getUri() + "?update=", json.toString(), 200) {\r
-\r
-                       @Override\r
-                       public void onComplete() {\r
-                               uploadFiles();\r
-                       }\r
-\r
-                       @Override\r
-                       public void onError(Throwable t) {\r
-                               GWT.log("", t);\r
-                               if (t instanceof RestException) {\r
-                                       int statusCode = ((RestException) t).getHttpStatusCode();\r
-                                       if (statusCode == 405)\r
-                                               GSS.get().displayError("You don't have the necessary permissions");\r
-                                       else if (statusCode == 404)\r
-                                               GSS.get().displayError("User in permissions does not exist");\r
-                                       else if (statusCode == 409)\r
-                                               GSS.get().displayError("A file with the same name already exists");\r
-                                       else if (statusCode == 413)\r
-                                               GSS.get().displayError("Your quota has been exceeded");\r
-                                       else\r
-                                               GSS.get().displayError("Unable to modify file:" +((RestException)t).getHttpStatusText());\r
-                               } else\r
-                                       GSS.get().displayError("System error modifying file:" + t.getMessage());\r
-                       }\r
-\r
-               };\r
-               DeferredCommand.addCommand(cf);\r
-       }\r
-\r
-       /**\r
-        * Schedule the PUT requests to upload the files.\r
-        */\r
-       private void uploadFiles() {\r
-               for (int i = 0; i< fileObjects.length; i++) {\r
-                       final int index = i;\r
-                       DeferredCommand.addCommand(new Command() {\r
-                               public void execute() {\r
-                                       doPut(fileObjects[index], index);\r
-                               }\r
-                       });\r
-               }\r
-       }\r
-\r
-       /**\r
-        * Perform the HTTP PUT requests to upload the specified file.\r
-        */\r
-       protected void doPut(final File file, final int index) {\r
-               GSS app = GSS.get();\r
-               HttpRequest request = factory.createHttpRequest();\r
-               String method = "PUT";\r
-\r
-               String path;\r
-               String filename = getFilename(file.getName());\r
-               FileResource selectedResource = getFileForName(filename);\r
-               if (selectedResource == null ) {\r
-                       // We are going to create a file.\r
-                       path = folder.getUri();\r
-                       if (!path.endsWith("/"))\r
-                               path = path + "/";\r
-                       path = path + encodeComponent(filename);\r
-               } else\r
-                       path = selectedResource.getUri();\r
-\r
-               String token = app.getToken();\r
-               String resource = path.substring(app.getApiPath().length()-1, path.length());\r
-               String date = RestCommand.getDate();\r
-               String sig = RestCommand.calculateSig(method, date, resource, RestCommand.base64decode(token));\r
-               request.open(method, path);\r
-               request.setRequestHeader("X-GSS-Date", date);\r
-               request.setRequestHeader("Authorization", app.getCurrentUserResource().getUsername() + " " + sig);\r
-               request.setRequestHeader("Accept", "application/json; charset=utf-8");\r
-               request.setCallback(new RequestCallback() {\r
-                       public void onResponseReceived(HttpRequest req) {\r
-                               switch(req.getStatus()) {\r
-                                       case 201: // Created falls through to updated.\r
-                                       case 204:\r
-                                               selectedFiles.remove(file);\r
-                                               finish();\r
-                                               break;\r
-                                       case 403:\r
-                                               SessionExpiredDialog dlg = new SessionExpiredDialog();\r
-                                               dlg.center();\r
-                                               break;\r
-                                       default:\r
-                                               DisplayHelper.log(req.getStatus() + ":" + req.getStatusText());\r
-                               }\r
-                       }\r
-               });\r
-               request.getUpload().setProgressHandler(new ProgressHandler() {\r
-                       public void onProgress(ProgressEvent event) {\r
-                               double pcnt = (double) event.getLoaded() / event.getTotal();\r
-                               progressBars.get(index).setProgress((int) Math.floor(pcnt * 100));\r
-                       }\r
-               });\r
-               request.send(file.getBlob());\r
-       }\r
-\r
-       /**\r
-        * Perform the final actions after the files are uploaded.\r
-        */\r
-       private void finish() {\r
-               if (!selectedFiles.isEmpty()) return;\r
-               hide();\r
-               GSS.get().showFileList(true);\r
-               GSS.get().getStatusPanel().updateStats();\r
-       }\r
-}\r
+/*
+ * Copyright 2009 Electronic Business Systems Ltd.
+ *
+ * This file is part of GSS.
+ *
+ * GSS is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GSS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GSS.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package gr.ebs.gss.client;
+
+import gr.ebs.gss.client.rest.PostCommand;
+import gr.ebs.gss.client.rest.RestCommand;
+import gr.ebs.gss.client.rest.RestException;
+import gr.ebs.gss.client.rest.resource.FileResource;
+import gr.ebs.gss.client.rest.resource.FolderResource;
+import gr.ebs.gss.client.rest.resource.RestResourceWrapper;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.gears.client.Factory;
+import com.google.gwt.gears.client.desktop.Desktop;
+import com.google.gwt.gears.client.desktop.File;
+import com.google.gwt.gears.client.desktop.OpenFilesHandler;
+import com.google.gwt.gears.client.httprequest.HttpRequest;
+import com.google.gwt.gears.client.httprequest.ProgressEvent;
+import com.google.gwt.gears.client.httprequest.ProgressHandler;
+import com.google.gwt.gears.client.httprequest.RequestCallback;
+import com.google.gwt.http.client.URL;
+import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.json.client.JSONString;
+import com.google.gwt.user.client.DeferredCommand;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.FlexTable;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+/**
+ * The 'File upload' dialog box implementation with Google Gears support.
+ */
+public class FileUploadGearsDialog extends FileUploadDialog implements Updateable {
+
+       protected final Factory factory = Factory.getInstance();
+
+       /**
+        * The array of files to upload.
+        */
+       private File[] fileObjects;
+
+       /**
+        * A list of files to upload, created from files array. Used to signal
+        * finished state when empty.
+        */
+       protected List<File> selectedFiles = new ArrayList<File>();
+
+       /**
+        * The list of progress bars for individual files.
+        */
+       protected List<ProgressBar> progressBars = new ArrayList<ProgressBar>();
+
+       private Button browse;
+
+       private Button submit;
+
+       private FlexTable generalTable;
+
+       private Map<String, FileResource> toRename;
+
+       protected List<HttpRequest> requests = new ArrayList<HttpRequest>();
+       
+       private boolean canContinue = true;
+
+       /**
+        * The widget's constructor.
+        */
+       public FileUploadGearsDialog() {
+               // Set the dialog's caption.
+               setText("File upload");
+               setAnimationEnabled(true);
+               // Create a panel to hold all of the dialog widgets.
+               VerticalPanel panel = new VerticalPanel();
+               final HTML info = new HTML("You may select one or more files to upload.");
+               info.addStyleName("gss-uploadNote");
+               panel.add(info);
+               // Add an informative label with the folder name.
+               Object selection = GSS.get().getTreeView().getSelection();
+               folder = ((RestResourceWrapper) selection).getResource();
+
+               browse = new Button("Browse...");
+
+               HorizontalPanel fileUploadPanel = new HorizontalPanel();
+               fileUploadPanel.add(browse);
+
+               generalTable = new FlexTable();
+               generalTable.setText(0, 0, "Folder");
+               generalTable.setText(1, 0, "File");
+               generalTable.setText(0, 1, folder.getName());
+               generalTable.setWidget(1, 1, fileUploadPanel);
+               generalTable.getCellFormatter().setStyleName(0, 0, "props-labels");
+               generalTable.getCellFormatter().setStyleName(1, 0, "props-labels");
+               generalTable.getCellFormatter().setStyleName(0, 1, "props-values");
+               generalTable.getCellFormatter().setStyleName(1, 1, "props-values");
+               generalTable.setCellSpacing(4);
+
+               panel.add(generalTable);
+
+               // Create a panel to hold the buttons.
+               HorizontalPanel buttons = new HorizontalPanel();
+
+               submit = new Button("Upload");
+               submit.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               prepareAndSubmit();
+                       }
+               });
+               submit.setEnabled(false);
+               buttons.add(submit);
+               buttons.setCellHorizontalAlignment(submit, HasHorizontalAlignment.ALIGN_CENTER);
+               // Create the 'Cancel' button, along with a listener that hides the
+               // dialog when the button is clicked.
+               Button cancel = new Button("Cancel", new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               canContinue = false;                            
+                               cancelUpload();                         
+                               GSS.get().showFileList(true);
+                       }
+               });
+               buttons.add(cancel);
+               buttons.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);
+               buttons.setSpacing(8);
+               buttons.addStyleName("gss-DialogBox");
+
+               browse.addClickHandler(new ClickHandler() {
+                       @Override
+                       public void onClick(ClickEvent event) {
+                               Desktop desktop = factory.createDesktop();
+                               desktop.openFiles(new OpenFilesHandler() {
+
+                                       @Override
+                                       public void onOpenFiles(OpenFilesEvent ofevent) {
+                                               fileObjects = ofevent.getFiles();
+                                               selectedFiles.addAll(Arrays.asList(fileObjects));
+                                               for (int i = 0; i< selectedFiles.size(); i++) {
+                                                       generalTable.setText(i+1, 0, "File");
+                                                       generalTable.setText(i+1, 1, selectedFiles.get(i).getName());
+                                                       ProgressBar progress = new ProgressBar(20, 0);
+                                                       generalTable.setWidget(i+1, 2, progress);
+                                                       progressBars.add(progress);
+                                                       generalTable.getCellFormatter().setStyleName(i+1, 0, "props-labels");
+                                                       generalTable.getCellFormatter().setStyleName(i+1, 1, "props-values");
+                                               }
+                                               submit.setEnabled(true);
+                                       }
+                               });
+                       }
+               });
+
+               panel.add(buttons);
+               panel.setCellHorizontalAlignment(buttons, HasHorizontalAlignment.ALIGN_CENTER);
+               panel.addStyleName("gss-DialogBox");
+               addStyleName("gss-DialogBox");
+               setWidget(panel);
+       }
+
+       /**
+        * Cancels the file upload.
+        */
+       private void cancelUpload() {
+               for (HttpRequest request: requests)
+                       request.abort();
+               hide();         
+       }
+
+       /**
+        * Check whether the specified file name exists in the selected folder.
+        */
+       private boolean canContinue(File file) {
+               String fileName = getFilename(file.getName());
+               if (getFileForName(fileName) == null)
+                       // For file creation, check to see if the file already exists.
+                       for (FileResource fileRes : files)
+                               if (!fileRes.isDeleted() && fileRes.getName().equals(fileName))
+                                       return false;
+               return true;
+       }
+
+       @Override
+       public void prepareAndSubmit() {
+               GSS app = GSS.get();
+               if (selectedFiles.size() == 0) {
+                       app.displayError("You must select a file!");
+                       hide();
+                       return;
+               }
+               for (File file: selectedFiles)
+                       if (!canContinue(file)) {
+                               app.displayError("The file name " + file.getName() +
+                                                       " already exists in this folder");
+                               hide();
+                               return;
+                       }
+               submit.setEnabled(false);
+               browse.setVisible(false);
+               List<String> toUpdate = new ArrayList<String>();
+               toRename = new HashMap<String, FileResource>();
+               for (File file: selectedFiles) {
+                       String fname = getFilename(file.getName());
+                       if (getFileForName(fname) == null) {
+                               // We are going to create a file, so we check to see if there is a
+                               // trashed file with the same name.
+                               FileResource same = null;
+                               for (FileResource fres : folder.getFiles())
+                                       if (fres.isDeleted() && fres.getName().equals(fname))
+                                               same = fres;
+                               // In that case add it to the list of files to rename.
+                               if (same != null)
+                                       toRename.put(getBackupFilename(fname), same);
+                       } else
+                               // If we are updating a file add it to the list of files to update.
+                               toUpdate.add(fname);
+               }
+
+               if (!toUpdate.isEmpty()) {
+                       StringBuffer sb = new StringBuffer();
+                       for (String name: toUpdate)
+                               sb.append(name).append("<br/>");
+                       // We are going to update existing files, so show a confirmation dialog.
+                       ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " +
+                                       "you want to update the following files?<br/><i>" + sb +
+                                       "</i>", "Update") {
+
+                               @Override
+                               public void cancel() {
+                                       hide();
+                               }
+
+                               @Override
+                               public void confirm() {
+                                       confirmRename();
+                               }
+
+                       };
+                       confirm.center();
+               } else
+                       confirmRename();
+       }
+
+       /**
+        * Confirm the renames of synonymous files already in the trash.
+        */
+       private void confirmRename() {
+               if (!toRename.isEmpty()) {
+                       StringBuffer sb = new StringBuffer();
+                       for (FileResource file: toRename.values())
+                               sb.append(file.getName()).append("<br/>");
+                       ConfirmationDialog confirm = new ConfirmationDialog("Files " +
+                                       "with the following names already exist in the trash. If" +
+                                       " you continue,<br/>the trashed files will be renamed " +
+                                       "automatically for you:<br/><i>" + sb + "</i>", "Continue") {
+
+                               @Override
+                               public void cancel() {
+                                       hide();
+                               }
+
+                               @Override
+                               public void confirm() {
+                                       updateTrashedFiles();
+                               }
+
+                       };
+                       confirm.center();
+               } else
+                       uploadFiles();
+       }
+
+       /**
+        * Rename the conflicting trashed files with the supplied new names.
+        */
+       private void updateTrashedFiles() {
+               for (final String name: toRename.keySet()) {
+                       JSONObject json = new JSONObject();
+                       json.put("name", new JSONString(name));
+                       PostCommand cf = new PostCommand(toRename.get(name).getUri() + "?update=", json.toString(), 200) {
+
+                               @Override
+                               public void onComplete() {
+                                       toRename.remove(name);
+                                       uploadFiles();
+                               }
+
+                               @Override
+                               public void onError(Throwable t) {
+                                       GSS app = GSS.get();
+                                       GWT.log("", t);
+                                       if (t instanceof RestException) {
+                                               int statusCode = ((RestException) t).getHttpStatusCode();
+                                               if (statusCode == 405)
+                                                       app.displayError("You don't have the necessary permissions");
+                                               else if (statusCode == 404)
+                                                       app.displayError("User in permissions does not exist");
+                                               else if (statusCode == 409)
+                                                       app.displayError("A file with the same name already exists");
+                                               else if (statusCode == 413)
+                                                       app.displayError("Your quota has been exceeded");
+                                               else
+                                                       app.displayError("Unable to modify file:" + ((RestException) t).getHttpStatusText());
+                                       } else
+                                               app.displayError("System error modifying file:" + t.getMessage());
+                               }
+
+                       };
+                       DeferredCommand.addCommand(cf);
+               }
+       }
+
+       /**
+        * Checks if the renaming step for already trashed files is complete and
+        * starts file uploads.
+        */
+       private void uploadFiles() {            
+               if (!toRename.isEmpty()) return;
+               if (canContinue){                                               
+                       doSend(selectedFiles);
+               }
+       }
+
+       /**
+        * Perform the HTTP request to upload the specified file.
+        */
+       protected void doSend(final List<File> filesRemaining) {
+               final GSS app = GSS.get();
+               HttpRequest request = factory.createHttpRequest();
+               requests.add(request);
+               String method = "PUT";
+
+               String path;
+               final String filename = getFilename(filesRemaining.get(0).getName());
+               path = folder.getUri();
+               if (!path.endsWith("/"))
+                       path = path + "/";
+               path = path + encode(filename);
+
+               String token = app.getToken();
+               String resource = path.substring(app.getApiPath().length()-1, path.length());
+               String date = RestCommand.getDate();
+               String sig = RestCommand.calculateSig(method, date, resource, RestCommand.base64decode(token));
+               request.open(method, path);
+               request.setRequestHeader("X-GSS-Date", date);
+               request.setRequestHeader("Authorization", app.getCurrentUserResource().getUsername() + " " + sig);
+               request.setRequestHeader("Accept", "application/json; charset=utf-8");
+               request.setCallback(new RequestCallback() {
+                       @Override
+                       public void onResponseReceived(HttpRequest req) {
+                               int state = req.getReadyState();
+                               if (state != 4) return;
+                               switch(req.getStatus()) {
+                                       case 201: // Created falls through to updated.
+                                       case 204:
+                                               filesRemaining.remove(0);
+                                               if(filesRemaining.isEmpty()){                                                   
+                                                       finish();
+                                                       break;
+                                               }                                               
+                                               doSend(filesRemaining);                         
+                                               break;
+                                       case 403:
+                                               SessionExpiredDialog dlg = new SessionExpiredDialog();
+                                               dlg.center();
+                                               break;
+                                       case 405:
+                                               app.displayError("You don't have permission to " +
+                                                               "upload file " + filename);
+                                               break;
+                                       case 409:
+                                               app.displayError("A folder with the name " + filename +
+                                                               " already exists at this level");
+                                               break;
+                                       case 413:
+                                               app.displayError("There is not enough free space " +
+                                                               "available for uploading " + filename);
+                                               break;
+                                       default:
+                                               app.displayError("Error uploading file " + filename +
+                                                                       ": " + req.getStatus());
+                               }
+                       }
+               });
+               request.getUpload().setProgressHandler(new ProgressHandler() {
+                       @Override
+                       public void onProgress(ProgressEvent event) {
+                               double pcnt = (double) event.getLoaded() / event.getTotal();
+                               progressBars.get(0).setProgress((int) Math.floor(pcnt * 100));
+                               if(pcnt*100 == 100)
+                                       progressBars.remove(0);
+                       }
+               });
+               request.send(filesRemaining.get(0).getBlob());
+       }
+
+       /**
+        * Perform the final actions after the files are uploaded.
+        */
+       protected void finish() {
+               hide();
+               //GSS.get().showFileList(true);
+               GSS.get().getTreeView().updateNode(GSS.get().getTreeView().getSelection());//showFileList(true);
+               GSS.get().getStatusPanel().updateStats();
+       }
+
+       /**
+        * Same as URL.encode, but also encode apostrophe since browsers aren't
+        * consistent about it (FF encodes, IE does not).
+        */
+       protected String encode(String decodedURL) {
+               String retv = decodedURL.replaceAll("@", "_"); // Replace bad character
+               retv = URL.encodeComponent(retv);
+               retv = retv.replaceAll("'", "%27");
+               return retv;
+       }
+
+}