Java tutorial
/* * 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 org.gss_project.gss.web.client; import org.gss_project.gss.web.client.rest.PostCommand; import org.gss_project.gss.web.client.rest.RestCommand; import org.gss_project.gss.web.client.rest.RestException; import org.gss_project.gss.web.client.rest.resource.FileResource; import org.gss_project.gss.web.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; } }