X-Git-Url: https://code.grnet.gr/git/pithos/blobdiff_plain/a8ede55340853936950dea858cbff6fba4ddd851..b4b6e89f4ac9275f96613cc1a645b5d7c867af7d:/src/gr/ebs/gss/client/FileUploadGearsDialog.java diff --git a/src/gr/ebs/gss/client/FileUploadGearsDialog.java b/src/gr/ebs/gss/client/FileUploadGearsDialog.java index fb843be..25203a8 100644 --- a/src/gr/ebs/gss/client/FileUploadGearsDialog.java +++ b/src/gr/ebs/gss/client/FileUploadGearsDialog.java @@ -26,7 +26,9 @@ import gr.ebs.gss.client.rest.resource.FolderResource; 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.gears.client.Factory; @@ -37,16 +39,17 @@ 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.Command; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; -import com.google.gwt.user.client.ui.Grid; +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.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; @@ -57,9 +60,31 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl private 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. + */ private List selectedFiles = new ArrayList(); - private TextBox selected; + /** + * The list of progress bars for individual files. + */ + private List progressBars = new ArrayList(); + + private Button browse; + + private Button submit; + + private FlexTable generalTable; + + private Map toRename; + + private List requests = new ArrayList(); /** * The widget's constructor. @@ -70,24 +95,19 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl 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().getFolders().getCurrent().getUserObject(); folder = (FolderResource) selection; - filenameLabel.setText(""); - filenameLabel.setVisible(false); - filenameLabel.setStyleName("props-labels"); - - final Button browse = new Button("Browse..."); - selected = new TextBox(); - selected.setEnabled(false); + browse = new Button("Browse..."); HorizontalPanel fileUploadPanel = new HorizontalPanel(); - fileUploadPanel.add(filenameLabel); - fileUploadPanel.add(selected); fileUploadPanel.add(browse); - Grid generalTable = new Grid(2, 2); + generalTable = new FlexTable(); generalTable.setText(0, 0, "Folder"); generalTable.setText(1, 0, "File"); generalTable.setText(0, 1, folder.getName()); @@ -103,26 +123,10 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl // Create a panel to hold the buttons. HorizontalPanel buttons = new HorizontalPanel(); - // Create the 'upload' button, along with a listener that submits the - // form. - final Button submit = new Button("Upload"); + submit = new Button("Upload"); submit.addClickListener(new ClickListener() { public void onClick(Widget sender) { - 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 specified file name already exists in this folder"); - hide(); - return; - } - submit.setEnabled(false); - browse.setVisible(false); prepareAndSubmit(); } }); @@ -134,7 +138,7 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl Button cancel = new Button("Cancel", new ClickListener() { public void onClick(Widget sender) { - hide(); + cancelUpload(); } }); buttons.add(cancel); @@ -148,8 +152,17 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl desktop.openFiles(new OpenFilesHandler() { public void onOpenFiles(OpenFilesEvent event) { - selectedFiles.addAll(Arrays.asList(event.getFiles())); - selected.setText(selectedFiles.get(0).getName()); + fileObjects = event.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); } }); @@ -157,17 +170,22 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl }); panel.add(buttons); - progressBar = new ProgressBar(50, ProgressBar.SHOW_TIME_REMAINING); - panel.add(progressBar); - progressBar.setVisible(false); panel.setCellHorizontalAlignment(buttons, HasHorizontalAlignment.ALIGN_CENTER); - panel.setCellHorizontalAlignment(progressBar, 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) { @@ -181,128 +199,166 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl } @Override - public void prepareAndSubmit(){ - final String fname = getFilename(selectedFiles.get(0).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; - if (same == null) - uploadFiles(); - else { - final FileResource sameFile = same; - GWT.log("Same deleted file", null); - ConfirmationDialog confirm = new ConfirmationDialog("A file " + - "with the same name exists in the trash. If you " + - "continue,
the trashed file '" + fname + - "' will be renamed automatically for you.", "Continue") { - - @Override - public void cancel() { - FileUploadGearsDialog.this.hide(); - } - - @Override - public void confirm() { - updateTrashedFile(getBackupFilename(fname), sameFile); - } - - }; - confirm.center(); + 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 toUpdate = new ArrayList(); + toRename = new HashMap(); + 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); } - else { - // We are going to update an existing file, so show a confirmation dialog. + + if (!toUpdate.isEmpty()) { + StringBuffer sb = new StringBuffer(); + for (String name: toUpdate) + sb.append(name).append("
"); + // We are going to update existing files, so show a confirmation dialog. ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " + - "you want to update " + fname + "?", "Update"){ + "you want to update the following files?
" + sb + + "", "Update") { @Override public void cancel() { - FileUploadGearsDialog.this.hide(); + hide(); } @Override public void confirm() { - uploadFiles(); + confirmRename(); } }; confirm.center(); - } + } else + confirmRename(); } - private void updateTrashedFile(String newName, FileResource trashedFile) { - JSONObject json = new JSONObject(); - json.put("name", new JSONString(newName)); - PostCommand cf = new PostCommand(trashedFile.getUri() + "?update=", json.toString(), 200) { + /** + * 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("
"); + ConfirmationDialog confirm = new ConfirmationDialog("Files " + + "with the following names already exist in the trash. If" + + " you continue,
the trashed files will be renamed " + + "automatically for you:
" + sb + "", "Continue") { - @Override - public void onComplete() { - uploadFiles(); - } + @Override + public void cancel() { + hide(); + } - @Override - public void onError(Throwable t) { - GWT.log("", t); - if (t instanceof RestException) { - int statusCode = ((RestException) t).getHttpStatusCode(); - if (statusCode == 405) - GSS.get().displayError("You don't have the necessary permissions"); - else if (statusCode == 404) - GSS.get().displayError("User in permissions does not exist"); - else if (statusCode == 409) - GSS.get().displayError("A file with the same name already exists"); - else if (statusCode == 413) - GSS.get().displayError("Your quota has been exceeded"); - else - GSS.get().displayError("Unable to modify file:" +((RestException)t).getHttpStatusText()); - } else - GSS.get().displayError("System error modifying file:" + t.getMessage()); - } + @Override + public void confirm() { + updateTrashedFiles(); + } - }; - DeferredCommand.addCommand(cf); + }; + confirm.center(); + } else + uploadFiles(); } /** - * Schedule the PUT requests to upload the files. + * 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() { - for (final File file: selectedFiles) + if (!toRename.isEmpty()) return; + for (int i = 0; i< fileObjects.length; i++) { + final int index = i; DeferredCommand.addCommand(new Command() { public void execute() { - doPut(file); + doPut(fileObjects[index], index); } }); + } } /** * Perform the HTTP PUT requests to upload the specified file. */ - protected void doPut(final File file) { - GSS app = GSS.get(); + protected void doPut(final File file, final int index) { + final GSS app = GSS.get(); HttpRequest request = factory.createHttpRequest(); + requests.add(request); String method = "PUT"; - fileNameToUse = getFilename(file.getName()); - selected.setVisible(false); - filenameLabel.setText(fileNameToUse); - filenameLabel.setVisible(true); - progressBar.setVisible(true); - String path; - FileResource selectedResource = getFileForName(fileNameToUse); - if (selectedResource == null ) { - // We are going to create a file. - path = folder.getUri(); - if (!path.endsWith("/")) - path = path + "/"; - path = path + encodeComponent(fileNameToUse); - } else - path = selectedResource.getUri(); + final String filename = getFilename(file.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()); @@ -324,7 +380,21 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl 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()); DisplayHelper.log(req.getStatus() + ":" + req.getStatusText()); } } @@ -332,7 +402,7 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl request.getUpload().setProgressHandler(new ProgressHandler() { public void onProgress(ProgressEvent event) { double pcnt = (double) event.getLoaded() / event.getTotal(); - progressBar.setProgress((int) Math.floor(pcnt * 100)); + progressBars.get(index).setProgress((int) Math.floor(pcnt * 100)); } }); request.send(file.getBlob()); @@ -347,4 +417,15 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl GSS.get().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). + */ + private String encode(String decodedURL) { + String retv = URL.encode(decodedURL); + retv = retv.replaceAll("'", "%27"); + return retv; + } + }