/*
* RHQ Management Platform
* Copyright (C) 2005-2010 Red Hat, Inc.
* All rights reserved.
*
* This program 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 version 2 of the License.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.coregui.client.components.upload;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.GWT;
import com.smartgwt.client.types.Encoding;
import com.smartgwt.client.widgets.form.events.FormSubmitFailedEvent;
import com.smartgwt.client.widgets.form.events.FormSubmitFailedHandler;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.FormItemIcon;
import com.smartgwt.client.widgets.form.fields.HiddenItem;
import com.smartgwt.client.widgets.form.fields.UploadItem;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import org.rhq.coregui.client.CoreGUI;
import org.rhq.coregui.client.ImageManager;
import org.rhq.coregui.client.UserSessionManager;
import org.rhq.coregui.client.util.message.Message;
import org.rhq.coregui.client.util.message.Message.Severity;
/**
* A base form widget for file upload. Uploaded files are uploaded to the server into a temp directory via
* FileUploadServlet.
*
* @author Jay Shaughnessy
*/
public class FileUploadForm extends DynamicCallbackForm {
private UploadItem fileUploadItem;
private ButtonItem uploadButton;
private Boolean uploadResult;
private String uploadError;
private boolean uploadInProgress;
private String name;
private String version;
private final boolean showNameLabel;
private final boolean showUploadButton;
private final FormItemIcon iconLoading;
private final FormItemIcon iconGreen;
private final FormItemIcon iconRed;
private final FormItemIcon iconGrey;
private List<String> uploadedFilePaths;
private String customTooltipMessage;
private boolean obfuscate;
public FileUploadForm(String name, String version, boolean showNameLabel, boolean showUploadButton,
Boolean isAlreadyUploaded) {
this(name, version, showNameLabel, showUploadButton, isAlreadyUploaded, false);
}
public FileUploadForm(String name, String version, boolean showNameLabel, boolean showUploadButton,
Boolean isAlreadyUploaded, boolean obfuscate) {
super(name);
this.name = name;
this.version = version;
this.showNameLabel = showNameLabel;
this.showUploadButton = showUploadButton;
this.uploadResult = isAlreadyUploaded; // null if unknown, false if error during previous upload attempt, true if already uploaded before
this.uploadInProgress = false;
this.customTooltipMessage = null;
this.obfuscate = obfuscate;
setEncoding(Encoding.MULTIPART);
setAction(GWT.getModuleBaseURL() + "/FileUploadServlet");
iconLoading = new FormItemIcon();
iconLoading.setSrc("ajax-loader.gif");
iconLoading.setWidth(16);
iconLoading.setHeight(16);
iconGreen = new FormItemIcon();
iconGreen.setSrc(ImageManager.getAvailabilityIcon(Boolean.TRUE));
iconGreen.setWidth(16);
iconGreen.setHeight(16);
iconRed = new FormItemIcon();
iconRed.setSrc(ImageManager.getAvailabilityIcon(Boolean.FALSE));
iconRed.setWidth(16);
iconRed.setHeight(16);
iconGrey = new FormItemIcon();
iconGrey.setSrc(ImageManager.getAvailabilityIcon(null));
iconGrey.setWidth(16);
iconGrey.setHeight(16);
}
/**
* The name of the file that is to be uploaded to the server. The actual client file can
* be named whatever, but the server will use this name as the name of the file.
* @return file name
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
onDraw();
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
onDraw();
}
public String getCustomTooltipMessage() {
return customTooltipMessage;
}
public void setCustomTooltipMessage(String tooltipMessage) {
this.customTooltipMessage = tooltipMessage;
}
/**
* If true, the server will be told to obfuscate the content of the file being uploaded when it saves it in order to
* help shield sensitive data.
*
* @return obfuscate flag
*/
public boolean isObfuscate() {
return obfuscate;
}
public void setObfuscate(boolean obfuscate) {
this.obfuscate = obfuscate;
onDraw();
}
/**
* Returns true if the user selected a file. This doesn't mean the file has been uploaded,
* just that a file has been selected at least for potentially being uploaded.
*
* @return true if file selected, false if no file has been selected yet
*/
public boolean isFileSelected() {
String value = fileUploadItem != null ? fileUploadItem.getValueAsString() : null;
return (value != null && !value.isEmpty());
}
/**
* Returns true if the file was successfully uploaded, false if an error occurred.
* Returns null if this upload form has not be submitted yet (see {@link #submitForm()}).
* @return status of the upload request
*/
public Boolean getUploadResult() {
return uploadResult;
}
/**
* @return Error text if {@link #getUploadResult()} returns false, otherwise null
*/
public String getUploadError() {
return uploadError;
}
private void setUploadError(String uploadError) {
this.uploadError = uploadError;
}
public boolean isUploadInProgress() {
return uploadInProgress;
}
@Override
public void reset() {
this.uploadError = null;
this.uploadInProgress = false;
this.uploadResult = null;
this.uploadedFilePaths = null;
changeIcon(iconGrey, (showUploadButton) ? MSG.view_upload_tooltip_1a() : MSG.view_upload_tooltip_1b());
super.reset();
}
@Override
public void submitForm() {
setUploadError(null);
if (uploadInProgress) {
String message = MSG.view_upload_inProgress();
setUploadError(message);
return;
}
if (!isFileSelected()) {
String message = MSG.view_upload_prompt_1(name);
changeIcon(iconRed, message);
setUploadError(message);
// note - don't even submit this definite failure
} else {
changeIcon(iconLoading, MSG.common_msg_loading());
uploadInProgress = true;
super.submitForm();
}
}
protected void changeIcon(FormItemIcon icon, String tooltip) {
FormItem item = (this.showUploadButton) ? this.uploadButton : this.fileUploadItem;
item.setIcons(icon);
item.setIconPrompt(tooltip);
markForRedraw();
}
protected List<FormItem> getOnDrawItems() {
List<FormItem> onDrawItems = new ArrayList<FormItem>();
HiddenItem sessionIdField = new HiddenItem("sessionid");
sessionIdField.setDefaultValue(UserSessionManager.getSessionSubject().getSessionId().intValue());
onDrawItems.add(sessionIdField);
HiddenItem nameField = new HiddenItem("name");
nameField.setDefaultValue(this.name);
onDrawItems.add(nameField);
HiddenItem versionField = new HiddenItem("version");
versionField.setDefaultValue(version);
onDrawItems.add(versionField);
HiddenItem obfuscateField = new HiddenItem("obfuscate");
obfuscateField.setDefaultValue(obfuscate);
onDrawItems.add(obfuscateField);
fileUploadItem = new UploadItem("fileUploadItem", name);
fileUploadItem.setShowTitle(showNameLabel);
fileUploadItem.setWrapTitle(false);
fileUploadItem.setColSpan(1);
if (getCustomTooltipMessage() != null) {
fileUploadItem.setPrompt(getCustomTooltipMessage());
fileUploadItem.setHoverWidth(300);
}
onDrawItems.add(fileUploadItem);
if (showUploadButton) {
uploadButton = new ButtonItem(MSG.view_upload_upload());
uploadButton.setColSpan(1);
uploadButton.setStartRow(false);
uploadButton.setAutoFit(true);
uploadButton.setIcon(ImageManager.getUploadIcon());
uploadButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent clickEvent) {
submitForm();
}
});
fileUploadItem.setEndRow(false);
onDrawItems.add(uploadButton);
}
if (uploadResult != null) {
if (uploadResult.booleanValue()) {
changeIcon(iconGreen, MSG.view_upload_alreadyUploaded());
} else {
String message = MSG.view_upload_tooltip_2();
changeIcon(iconRed, message);
setUploadError(message);
}
} else {
changeIcon(iconGrey, (showUploadButton) ? MSG.view_upload_tooltip_1a() : MSG.view_upload_tooltip_1b());
}
return onDrawItems;
}
protected DynamicFormHandler getSubmitCompleteHandler() {
return new DynamicFormHandler() {
public void onSubmitComplete(DynamicFormSubmitCompleteEvent event) {
uploadInProgress = false;
String results = event.getResults();
if (processSubmitCompleteResults(results)) {
uploadResult = Boolean.TRUE;
changeIcon(iconGreen, MSG.view_upload_success());
CoreGUI.getMessageCenter().notify(new Message(MSG.view_upload_success(), results, Severity.Info));
} else {
uploadResult = Boolean.FALSE;
String cause = "[" + name + "] " + parseCauseFromResponse(results);
changeIcon(iconRed, cause);
setUploadError(cause);
CoreGUI.getMessageCenter().notify(
new Message(MSG.view_upload_error_fileName(name), results, Severity.Error));
}
}
};
}
protected FormSubmitFailedHandler getSubmitFailedHandler() {
return new FormSubmitFailedHandler() {
public void onFormSubmitFailed(FormSubmitFailedEvent event) {
uploadInProgress = false;
uploadResult = Boolean.FALSE;
String cause = MSG.view_upload_error_fileName_2(name);
changeIcon(iconRed, cause);
setUploadError(cause);
CoreGUI.getMessageCenter().notify(new Message(cause, Severity.Error));
}
};
}
@Override
protected void onDraw() {
super.onDraw();
//set the number of columns before we create the items so that
//they have this value available
setNumCols(((this.showUploadButton) ? 2 : 1) + ((this.showNameLabel) ? 1 : 0));
List<FormItem> onDrawItems = getOnDrawItems();
setItems(onDrawItems.toArray(new FormItem[onDrawItems.size()]));
// push the form handler so it executes first if the form creator has also added a handler
DynamicFormHandler submitCompleteHandler = getSubmitCompleteHandler();
if (null != submitCompleteHandler) {
pushFormHandler(submitCompleteHandler);
}
FormSubmitFailedHandler submitFailedHandler = getSubmitFailedHandler();
if (null != submitFailedHandler) {
this.addFormSubmitFailedHandler(submitFailedHandler);
}
}
public List<String> getUploadedFilePaths() {
return uploadedFilePaths;
}
protected boolean processSubmitCompleteResults(String submitCompleteEventResults) {
if (null == uploadedFilePaths) {
uploadedFilePaths = this.parseFilePathsFromResponse(submitCompleteEventResults);
}
return !(null == uploadedFilePaths || uploadedFilePaths.isEmpty());
}
private List<String> parseFilePathsFromResponse(String results) {
List<String> files = null;
try {
files = new ArrayList<String>();
if (results != null) {
String[] allLines = results.split("\n");
for (String line : allLines) {
String trimmedLine = line.trim();
if (!trimmedLine.endsWith("html>")) {
files.add(trimmedLine);
}
}
}
} catch (Exception e) {
CoreGUI.getErrorHandler().handleError(MSG.view_upload_error_results(results), e);
}
return files;
}
private String parseCauseFromResponse(String results) {
int i = (null == results) ? -1 : results.indexOf("\tat ");
String cause = (-1 == i) ? results : results.substring(0, i);
return cause;
}
}