X-Git-Url: https://code.grnet.gr/git/pithos/blobdiff_plain/204107fb7bb5d2b059bdb36f1c795bc5e7d2195b..0d8cfb8f0bbdd172a2811d5add29985b8345af71:/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 1a58633..ef5b0f1 100644 --- a/src/gr/ebs/gss/client/FileUploadGearsDialog.java +++ b/src/gr/ebs/gss/client/FileUploadGearsDialog.java @@ -1,352 +1,442 @@ -/* - * 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 . - */ -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 java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.google.gwt.core.client.GWT; -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.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.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; - -/** - * The 'File upload' dialog box implementation with Google Gears support. - */ -public class FileUploadGearsDialog extends FileUploadDialog implements Updateable { - - private final Factory factory = Factory.getInstance(); - - private List selectedFiles = new ArrayList(); - - private TextBox selected; - - private Button browse; - - private Button submit; - - /** - * 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(); - // 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"); - - browse = new Button("Browse..."); - - selected = new TextBox(); - selected.setEnabled(false); - - HorizontalPanel fileUploadPanel = new HorizontalPanel(); - fileUploadPanel.add(filenameLabel); - fileUploadPanel.add(selected); - fileUploadPanel.add(browse); - - Grid generalTable = new Grid(2, 2); - 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.addClickListener(new ClickListener() { - - public void onClick(Widget sender) { - 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 ClickListener() { - - public void onClick(Widget sender) { - hide(); - } - }); - buttons.add(cancel); - buttons.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER); - buttons.setSpacing(8); - buttons.addStyleName("gss-DialogBox"); - - browse.addClickListener(new ClickListener() { - public void onClick(Widget sender) { - Desktop desktop = factory.createDesktop(); - desktop.openFiles(new OpenFilesHandler() { - - public void onOpenFiles(OpenFilesEvent event) { - selectedFiles.addAll(Arrays.asList(event.getFiles())); - selected.setText(selectedFiles.get(0).getName()); - submit.setEnabled(true); - } - }); - } - }); - - 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); - } - - /** - * 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); - 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() { - hide(); - } - - @Override - public void confirm() { - updateTrashedFile(getBackupFilename(fname), sameFile); - } - - }; - confirm.center(); - } - } else { - // We are going to update an existing file, so show a confirmation dialog. - ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " + - "you want to update " + fname + "?", "Update"){ - - @Override - public void cancel() { - hide(); - } - - @Override - public void confirm() { - uploadFiles(); - } - - }; - confirm.center(); - } - } - - 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) { - - @Override - public void onComplete() { - uploadFiles(); - } - - @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()); - } - - }; - DeferredCommand.addCommand(cf); - } - - /** - * Schedule the PUT requests to upload the files. - */ - private void uploadFiles() { - for (final File file: selectedFiles) - DeferredCommand.addCommand(new Command() { - public void execute() { - doPut(file); - } - }); - } - - /** - * Perform the HTTP PUT requests to upload the specified file. - */ - protected void doPut(final File file) { - GSS app = GSS.get(); - HttpRequest request = factory.createHttpRequest(); - 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(); - - 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() { - public void onResponseReceived(HttpRequest req) { - switch(req.getStatus()) { - case 201: // Created falls through to updated. - case 204: - selectedFiles.remove(file); - finish(); - break; - case 403: - SessionExpiredDialog dlg = new SessionExpiredDialog(); - dlg.center(); - break; - default: - DisplayHelper.log(req.getStatus() + ":" + req.getStatusText()); - } - } - }); - request.getUpload().setProgressHandler(new ProgressHandler() { - public void onProgress(ProgressEvent event) { - double pcnt = (double) event.getLoaded() / event.getTotal(); - progressBar.setProgress((int) Math.floor(pcnt * 100)); - } - }); - request.send(file.getBlob()); - } - - /** - * Perform the final actions after the files are uploaded. - */ - private void finish() { - if (!selectedFiles.isEmpty()) return; - hide(); - GSS.get().showFileList(true); - GSS.get().getStatusPanel().updateStats(); - } -} +/* + * 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 . + */ +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 selectedFiles = new ArrayList(); + + /** + * The list of progress bars for individual files. + */ + protected List progressBars = new ArrayList(); + + private Button browse; + + private Button submit; + + private FlexTable generalTable; + + private Map toRename; + + protected List requests = new ArrayList(); + + 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 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); + } + + 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 the following files?
" + sb + + "", "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("
"); + 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 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 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; + } + +}