Refactored UploadHandler.java to update upload status using eventing

Signed-off-by: Asharani <asharani.murugesh@in.bosch.com>
This commit is contained in:
Asharani
2016-05-12 15:16:41 +05:30
parent 887536b2b7
commit 8fc1f74f80
8 changed files with 374 additions and 178 deletions

View File

@@ -254,5 +254,10 @@
<artifactId>allure-junit-adaptor</artifactId> <artifactId>allure-junit-adaptor</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.10.4</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -16,5 +16,5 @@ package org.eclipse.hawkbit.ui.artifacts.event;
*/ */
public enum UploadArtifactUIEvent { public enum UploadArtifactUIEvent {
SHOW_DROP_HINTS, HIDE_DROP_HINTS, SOFTWARE_DRAG_START, SOFTWARE_TYPE_DRAG_START, UPDATE_UPLOAD_COUNT, ENABLE_PROCESS_BUTTON, HIDE_FILTER_BY_TYPE, SHOW_FILTER_BY_TYPE, DISCARD_DELETE_SOFTWARE, DISCARD_ALL_DELETE_SOFTWARE, DELETED_ALL_SOFWARE, DISABLE_PROCESS_BUTTON, DISCARD_DELETE_SOFTWARE_TYPE, DISCARD_ALL_DELETE_SOFTWARE_TYPE, DELETED_ALL_SOFWARE_TYPE,MINIMIZED_STATUS_POPUP,MAXIMIZED_STATUS_POPUP,UPLOAD_FINISHED,UPLOAD_STARTED, UPLOAD_STREAMINING_FINISHED SHOW_DROP_HINTS, HIDE_DROP_HINTS, SOFTWARE_DRAG_START, SOFTWARE_TYPE_DRAG_START, UPDATE_UPLOAD_COUNT, ENABLE_PROCESS_BUTTON, HIDE_FILTER_BY_TYPE, SHOW_FILTER_BY_TYPE, DISCARD_DELETE_SOFTWARE, DISCARD_ALL_DELETE_SOFTWARE, DELETED_ALL_SOFWARE, DISABLE_PROCESS_BUTTON, DISCARD_DELETE_SOFTWARE_TYPE, DISCARD_ALL_DELETE_SOFTWARE_TYPE, DELETED_ALL_SOFWARE_TYPE,MINIMIZED_STATUS_POPUP,MAXIMIZED_STATUS_POPUP, UPLOAD_IN_PROGESS
} }

View File

@@ -0,0 +1,60 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.artifacts.event;
import java.io.Serializable;
/**
*
* Holds file and upload status details.
*
*/
public class UploadFileStatus implements Serializable {
private static final long serialVersionUID = -3599629192216760811L;
private String fileName;
private long contentLength;
private long bytesRead;
private String failureReason;
public UploadFileStatus(String fileName){
this.fileName = fileName;
}
public UploadFileStatus(String fileName, long bytesRead, long contentLength) {
this.fileName = fileName;
this.contentLength = contentLength;
this.bytesRead = bytesRead;
}
public UploadFileStatus(String fileName, String failureReason) {
this.failureReason = failureReason;
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public long getContentLength() {
return contentLength;
}
public long getBytesRead() {
return bytesRead;
}
public String getFailureReason() {
return failureReason;
}
}

View File

@@ -0,0 +1,34 @@
package org.eclipse.hawkbit.ui.artifacts.event;
/**
*
* Holds the upload file status.
*
*/
public class UploadStatusEvent {
public enum UploadStatusEventType {
UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED
}
private UploadStatusEventType uploadProgressEventType;
private UploadFileStatus uploadStatus;
public UploadStatusEvent(UploadStatusEventType eventType, UploadFileStatus entity) {
this.uploadProgressEventType = eventType;
this.uploadStatus = entity;
}
public UploadFileStatus getUploadStatus() {
return uploadStatus;
}
public void setUploadStatus(UploadFileStatus uploadStatus) {
this.uploadStatus = uploadStatus;
}
public UploadStatusEventType getUploadProgressEventType() {
return uploadProgressEventType;
}
}

View File

@@ -17,6 +17,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.upload.UploadStatusObject; import org.eclipse.hawkbit.ui.artifacts.upload.UploadStatusObject;
@@ -68,6 +69,19 @@ public class ArtifactUploadState implements ManagmentEntityState<Long>, Serializ
private List<UploadStatusObject> uploadedFileStatusList = new ArrayList<>(); private List<UploadStatusObject> uploadedFileStatusList = new ArrayList<>();
private final AtomicInteger numberOfFileUploadsExpected = new AtomicInteger();
private final AtomicInteger numberOfFilesActuallyUpload = new AtomicInteger();
public AtomicInteger getNumberOfFilesActuallyUpload() {
return numberOfFilesActuallyUpload;
}
public AtomicInteger getNumberOfFileUploadsExpected() {
return numberOfFileUploadsExpected;
}
public List<UploadStatusObject> getUploadedFileStatusList() { public List<UploadStatusObject> getUploadedFileStatusList() {
return uploadedFileStatusList; return uploadedFileStatusList;
} }

View File

@@ -12,9 +12,10 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException; import org.eclipse.hawkbit.repository.exception.ArtifactUploadFailedException;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile; import org.eclipse.hawkbit.ui.artifacts.event.UploadFileStatus;
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -59,30 +60,29 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
private final long fileSize; private final long fileSize;
private final UploadLayout view; private final UploadLayout view;
private final UploadStatusInfoWindow infoWindow;
private final long maxSize; private final long maxSize;
private final Upload upload; private final Upload upload;
private volatile String fileName = null; private volatile String fileName = null;
private volatile String mimeType = null; private volatile String mimeType = null;
private volatile boolean interrupted = false; private volatile boolean streamingInterrupted = false;
private volatile boolean uploadInterrupted = false;
private String failureReason; private String failureReason;
private final I18N i18n; private final I18N i18n;
private transient EventBus.SessionEventBus eventBus; private transient EventBus.SessionEventBus eventBus;
UploadHandler(final String fileName, final long fileSize, final UploadLayout view, UploadHandler(final String fileName, final long fileSize, final UploadLayout view,
final UploadStatusInfoWindow infoWindow, final long maxSize, final Upload upload, final String mimeType) { final long maxSize, final Upload upload, final String mimeType) {
super(); super();
this.fileName = fileName; this.fileName = fileName;
this.fileSize = fileSize; this.fileSize = fileSize;
this.view = view; this.view = view;
this.infoWindow = infoWindow;
this.maxSize = maxSize; this.maxSize = maxSize;
this.upload = upload; this.upload = upload;
this.mimeType = mimeType; this.mimeType = mimeType;
this.i18n = SpringContextHelper.getBean(I18N.class); this.i18n = SpringContextHelper.getBean(I18N.class);
this.eventBus = SpringContextHelper.getBean(EventBus.SessionEventBus.class); this.eventBus = SpringContextHelper.getBean(EventBus.SessionEventBus.class);
} }
/** /**
@@ -97,7 +97,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
} catch (final ArtifactUploadFailedException e) { } catch (final ArtifactUploadFailedException e) {
LOG.error("Atifact upload failed {} ", e); LOG.error("Atifact upload failed {} ", e);
failureReason = e.getMessage(); failureReason = e.getMessage();
interrupted = true; streamingInterrupted = true;
return new NullOutputStream(); return new NullOutputStream();
} }
} }
@@ -112,7 +112,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
public OutputStream receiveUpload(final String fileName, final String mimeType) { public OutputStream receiveUpload(final String fileName, final String mimeType) {
this.fileName = fileName; this.fileName = fileName;
this.mimeType = mimeType; this.mimeType = mimeType;
//reset has directory flag before upload // reset has directory flag before upload
view.setHasDirectory(false); view.setHasDirectory(false);
try { try {
if (view.checkIfSoftwareModuleIsSelected()) { if (view.checkIfSoftwareModuleIsSelected()) {
@@ -127,6 +127,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
LOG.error("Atifact upload failed {} ", e); LOG.error("Atifact upload failed {} ", e);
failureReason = e.getMessage(); failureReason = e.getMessage();
upload.interruptUpload(); upload.interruptUpload();
uploadInterrupted = true;
} }
// if final validation fails ,final no upload ,return NullOutputStream // if final validation fails ,final no upload ,return NullOutputStream
return new NullOutputStream(); return new NullOutputStream();
@@ -141,13 +142,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
@Override @Override
public void uploadSucceeded(final SucceededEvent event) { public void uploadSucceeded(final SucceededEvent event) {
LOG.debug("Streaming finished for file :{}", event.getFilename()); LOG.debug("Streaming finished for file :{}", event.getFilename());
view.updateFileSize(event.getFilename(), event.getLength()); eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_SUCCESSFUL, new UploadFileStatus(
event.getFilename(), 0, event.getLength())));
// recorded that we now one more uploaded
view.increaseNumberOfFilesActuallyUpload();
// inform upload status window
infoWindow.uploadSucceeded(event.getFilename());
} }
/** /**
@@ -160,20 +156,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
@Override @Override
public void streamingFinished(final StreamingEndEvent event) { public void streamingFinished(final StreamingEndEvent event) {
LOG.debug("Streaming finished for file :{}", event.getFileName()); LOG.debug("Streaming finished for file :{}", event.getFileName());
// record that we now one more uploaded eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STREAMING_FINISHED,
view.increaseNumberOfFilesActuallyUpload(); new UploadFileStatus(event.getFileName(), 0, event.getContentLength())));
// inform upload status window
infoWindow.uploadSucceeded(event.getFileName());
// check if we are finished
if (view.enableProcessBtn()) {
infoWindow.uploadSessionFinished();
}
eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED);
// display the duplicate message after streaming all files
view.displayDuplicateValidationMessage();
} }
/** /**
@@ -185,12 +169,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
@Override @Override
public void uploadFinished(final FinishedEvent event) { public void uploadFinished(final FinishedEvent event) {
LOG.debug("Upload finished for file :{}", event.getFilename()); LOG.debug("Upload finished for file :{}", event.getFilename());
// check if we are finished eventBus.publish(this,
if (view.enableProcessBtn()) { new UploadStatusEvent(UploadStatusEventType.UPLOAD_FINISHED, new UploadFileStatus(event.getFilename())));
infoWindow.uploadSessionFinished();
}
view.updateActionCount();
} }
/** /**
@@ -201,7 +181,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
@Override @Override
public void streamingStarted(final StreamingStartEvent event) { public void streamingStarted(final StreamingStartEvent event) {
LOG.debug("Streaming started for file :{}", fileName); LOG.debug("Streaming started for file :{}", fileName);
infoWindow.uploadStarted(fileName); eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED, new UploadFileStatus(
fileName, 0, 0)));
} }
/** /**
@@ -213,12 +194,14 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
public void uploadStarted(final StartedEvent event) { public void uploadStarted(final StartedEvent event) {
// single file session // single file session
if (view.isSoftwareModuleSelected() && !view.checkIfFileIsDuplicate(event.getFilename())) { if (view.isSoftwareModuleSelected() && !view.checkIfFileIsDuplicate(event.getFilename())) {
infoWindow.uploadSessionStarted();
LOG.debug("Upload started for file :{}", event.getFilename()); LOG.debug("Upload started for file :{}", event.getFilename());
infoWindow.uploadStarted(event.getFilename()); eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED, new UploadFileStatus(
event.getFilename(), 0, 0)));
} else { } else {
failureReason = i18n.get("message.upload.failed"); failureReason = i18n.get("message.upload.failed");
upload.interruptUpload(); upload.interruptUpload();
// actual interrupt will happen a bit late so setting the below flag
uploadInterrupted = true;
} }
} }
@@ -239,23 +222,21 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
*/ */
@Override @Override
public void updateProgress(final long readBytes, final long contentLength) { public void updateProgress(final long readBytes, final long contentLength) {
if (readBytes > maxSize || contentLength > maxSize) { //Update progress is called event after upload interrupted in uploadStarted method
LOG.error("User tried to upload more than was allowed ({}).", maxSize); if (!uploadInterrupted) {
if (readBytes > maxSize || contentLength > maxSize) {
view.decreaseNumberOfFileUploadsExpected(); LOG.error("User tried to upload more than was allowed ({}).", maxSize);
final SoftwareModule sw = view.getSoftwareModuleSelected(); failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize);
view.getFileSelected().remove(new CustomFile(fileName, sw.getName(), sw.getVersion())); eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED, new UploadFileStatus(
view.updateActionCount(); fileName, failureReason)));
upload.interruptUpload();
failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize); uploadInterrupted = true;
infoWindow.uploadFailed(fileName, failureReason); return;
upload.interruptUpload(); }
interrupted = true; eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS,
return; new UploadFileStatus(fileName, readBytes, contentLength)));
LOG.info("Update progress - {} : {}", fileName, (double) readBytes / (double) contentLength);
} }
infoWindow.updateProgress(fileName, readBytes, contentLength);
LOG.info("Update progress - {} : {}", fileName, (double) readBytes / (double) contentLength);
} }
/** /**
@@ -267,19 +248,14 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
public void onProgress(final StreamingProgressEvent event) { public void onProgress(final StreamingProgressEvent event) {
if (event.getBytesReceived() > maxSize || event.getContentLength() > maxSize) { if (event.getBytesReceived() > maxSize || event.getContentLength() > maxSize) {
LOG.error("User tried to upload more than was allowed ({}).", maxSize); LOG.error("User tried to upload more than was allowed ({}).", maxSize);
view.decreaseNumberOfFileUploadsExpected();
final SoftwareModule sw = view.getSoftwareModuleSelected();
view.getFileSelected().remove(new CustomFile(fileName, sw.getName(), sw.getVersion()));
eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED);
failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize); failureReason = i18n.get("message.uploadedfile.size.exceeded", maxSize);
infoWindow.uploadFailed(event.getFileName(), failureReason); eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED, new UploadFileStatus(
interrupted = true; fileName, failureReason)));
streamingInterrupted = true;
return; return;
} }
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS, new UploadFileStatus(
infoWindow.updateProgress(event.getFileName(), event.getBytesReceived(), event.getContentLength()); fileName, event.getBytesReceived(), event.getContentLength())));
// Logging to solve sonar issue // Logging to solve sonar issue
LOG.trace("Streaming in progress for file :{}", event.getFileName()); LOG.trace("Streaming in progress for file :{}", event.getFileName());
} }
@@ -293,29 +269,15 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
@Override @Override
public void streamingFailed(final StreamingErrorEvent event) { public void streamingFailed(final StreamingErrorEvent event) {
LOG.info("Streaming failed for file :{}", event.getFileName()); LOG.info("Streaming failed for file :{}", event.getFileName());
if (failureReason == null) {
view.decreaseNumberOfFileUploadsExpected(); failureReason = event.getException().getMessage();
final SoftwareModule sw = view.getSoftwareModuleSelected();
view.getFileSelected().remove(new CustomFile(fileName, sw.getName(), sw.getVersion()));
eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED);
if (failureReason != null) {
// Display custom error message
infoWindow.uploadFailed(event.getFileName(), failureReason);
} else {
// internal upload error
infoWindow.uploadFailed(event.getFileName(), event.getException().getMessage());
} }
// check if we are finished eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STREAMING_FAILED,
if (view.enableProcessBtn()) { new UploadFileStatus(fileName, failureReason)));
infoWindow.uploadSessionFinished();
}
view.displayDuplicateValidationMessage();
LOG.info("Streaming failed due to :{}", event.getException()); LOG.info("Streaming failed due to :{}", event.getException());
} }
/** /**
* Upload failed for {@link Upload} variant. * Upload failed for {@link Upload} variant.
* *
@@ -324,23 +286,13 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
@Override @Override
public void uploadFailed(final FailedEvent event) { public void uploadFailed(final FailedEvent event) {
LOG.info("Upload failed for file :{}", event.getFilename()); LOG.info("Upload failed for file :{}", event.getFilename());
view.decreaseNumberOfFileUploadsExpected(); if (failureReason == null) {
/** failureReason = event.getReason().getMessage();
* If upload interrupted because of duplicate file,do not remove the
* file already in upload list
**/
if (!view.getDuplicateFileNamesList().isEmpty()) {
final SoftwareModule sw = view.getSoftwareModuleSelected();
view.getFileSelected().remove(new CustomFile(fileName, sw.getName(), sw.getVersion()));
}
eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED);
if (failureReason != null) {
infoWindow.uploadFailed(event.getFilename(), failureReason);
} else {
infoWindow.uploadFailed(event.getFilename(), event.getReason().getMessage());
} }
System.out.println("failureReason:::"+failureReason);
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED, new UploadFileStatus(
fileName, failureReason)));
LOG.info("Upload failed for file :{}", event.getReason()); LOG.info("Upload failed for file :{}", event.getReason());
} }
/** /**
@@ -348,7 +300,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
*/ */
@Override @Override
public boolean isInterrupted() { public boolean isInterrupted() {
return interrupted; return streamingInterrupted;
} }
private static class NullOutputStream extends OutputStream { private static class NullOutputStream extends OutputStream {

View File

@@ -16,7 +16,6 @@ import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
@@ -26,6 +25,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile; import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
@@ -97,13 +98,9 @@ public class UploadLayout extends VerticalLayout {
@Autowired @Autowired
private transient SPInfo spInfo; private transient SPInfo spInfo;
private final AtomicInteger numberOfFileUploadsExpected = new AtomicInteger();
private final AtomicInteger numberOfFilesActuallyUpload = new AtomicInteger();
private final List<String> duplicateFileNamesList = new ArrayList<>(); private final List<String> duplicateFileNamesList = new ArrayList<>();
private Button processBtn ; private Button processBtn;
private Button discardBtn; private Button discardBtn;
@@ -128,12 +125,49 @@ public class UploadLayout extends VerticalLayout {
void init() { void init() {
createComponents(); createComponents();
buildLayout(); buildLayout();
updateActionCount();
restoreState(); restoreState();
eventBus.subscribe(this); eventBus.subscribe(this);
ui = UI.getCurrent(); ui = UI.getCurrent();
} }
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) {
ui.access(() -> updateActionCount());
} else if (event == UploadArtifactUIEvent.MINIMIZED_STATUS_POPUP) {
ui.access(() -> showUploadStatusButton());
} else if (event == UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP) {
ui.access(() -> maximizeStatusPopup());
}
}
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final UploadStatusEvent event) {
if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STARTED) {
ui.access(() -> setUploadStatusButtonIconToInProgress());
}
else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_FAILED) {
ui.access(() -> onUploadFailure(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_FINISHED) {
ui.access(() -> onUploadCompletion());
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_SUCCESSFUL) {
ui.access(() -> onUploadSuccess(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FAILED) {
ui.access(() -> onUploadStreamingFailure(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FINISHED) {
ui.access(() -> onUploadStreamingSuccess(event));
}
}
@PreDestroy
void destroy() {
/*
* It's good manners to do this, even though vaadin-spring will
* automatically unsubscribe when this UI is garbage collected.
*/
eventBus.unsubscribe(this);
}
private void createComponents() { private void createComponents() {
createUploadStatusButton(); createUploadStatusButton();
createProcessButton(); createProcessButton();
@@ -143,8 +177,8 @@ public class UploadLayout extends VerticalLayout {
private void buildLayout() { private void buildLayout() {
final Upload upload = new Upload(); final Upload upload = new Upload();
final UploadHandler uploadHandler = new UploadHandler(null, 0, this, uploadInfoWindow, final UploadHandler uploadHandler = new UploadHandler(null, 0, this, spInfo.getMaxArtifactFileSize(), upload,
spInfo.getMaxArtifactFileSize(), upload, null); null);
upload.setButtonCaption(i18n.get("upload.file")); upload.setButtonCaption(i18n.get("upload.file"));
upload.setImmediate(true); upload.setImmediate(true);
upload.setReceiver(uploadHandler); upload.setReceiver(uploadHandler);
@@ -176,9 +210,15 @@ public class UploadLayout extends VerticalLayout {
} }
private void restoreState() { private void restoreState() {
updateActionCount();
if (!artifactUploadState.getFileSelected().isEmpty() && artifactUploadState.isUploadCompleted()) {
processBtn.setEnabled(true);
}
if (artifactUploadState.isStatusPopupMinimized()) { if (artifactUploadState.isStatusPopupMinimized()) {
showUploadStatusButton(); showUploadStatusButton();
setUploadStatusButtonIconToFinished(); if (artifactUploadState.isUploadCompleted()) {
setUploadStatusButtonIconToFinished();
}
} }
} }
@@ -204,10 +244,10 @@ public class UploadLayout extends VerticalLayout {
for (final Html5File file : files) { for (final Html5File file : files) {
processFile(file); processFile(file);
} }
if (numberOfFileUploadsExpected.get() > 0) { if (artifactUploadState.getNumberOfFileUploadsExpected().get() > 0) {
processBtn.setEnabled(false); processBtn.setEnabled(false);
// reset before we start // reset before we start
uploadInfoWindow.uploadSessionStarted(); // uploadInfoWindow.uploadSessionStarted();
} else { } else {
// If the upload is not started, it signifies all // If the upload is not started, it signifies all
// dropped files as either duplicate or directory.So // dropped files as either duplicate or directory.So
@@ -220,7 +260,7 @@ public class UploadLayout extends VerticalLayout {
private void processFile(final Html5File file) { private void processFile(final Html5File file) {
if (!isDirectory(file)) { if (!isDirectory(file)) {
if (!checkForDuplicate(file.getFileName())) { if (!checkForDuplicate(file.getFileName())) {
numberOfFileUploadsExpected.incrementAndGet(); artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet();
file.setStreamVariable(createStreamVariable(file)); file.setStreamVariable(createStreamVariable(file));
} }
} else { } else {
@@ -229,7 +269,7 @@ public class UploadLayout extends VerticalLayout {
} }
private StreamVariable createStreamVariable(final Html5File file) { private StreamVariable createStreamVariable(final Html5File file) {
return new UploadHandler(file.getFileName(), file.getFileSize(), UploadLayout.this, uploadInfoWindow, return new UploadHandler(file.getFileName(), file.getFileSize(), UploadLayout.this,
spInfo.getMaxArtifactFileSize(), null, file.getType()); spInfo.getMaxArtifactFileSize(), null, file.getType());
} }
@@ -282,9 +322,7 @@ public class UploadLayout extends VerticalLayout {
processBtn.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON); processBtn.addStyleName(SPUIStyleDefinitions.ACTION_BUTTON);
processBtn.addClickListener(event -> displayConfirmWindow(event)); processBtn.addClickListener(event -> displayConfirmWindow(event));
processBtn.setHtmlContentAllowed(true); processBtn.setHtmlContentAllowed(true);
if (artifactUploadState.getFileSelected().isEmpty()) { processBtn.setEnabled(false);
processBtn.setEnabled(false);
}
} }
private void createDiscardBtn() { private void createDiscardBtn() {
@@ -349,13 +387,15 @@ public class UploadLayout extends VerticalLayout {
artifactUploadState.getBaseSwModuleList().put(currentBaseSoftwareModuleKey, selectedSoftwareModule); artifactUploadState.getBaseSwModuleList().put(currentBaseSoftwareModuleKey, selectedSoftwareModule);
} }
return out; return out;
} catch (final FileNotFoundException e) { }
catch (final FileNotFoundException e) {
LOG.error("Upload failed {}", e); LOG.error("Upload failed {}", e);
throw new ArtifactUploadFailedException(i18n.get("message.file.not.found")); throw new ArtifactUploadFailedException(i18n.get("message.file.not.found"));
} catch (final IOException e) { } catch (final IOException e) {
LOG.error("Upload failed {}", e); LOG.error("Upload failed {}", e);
throw new ArtifactUploadFailedException(i18n.get("message.upload.failed")); throw new ArtifactUploadFailedException(i18n.get("message.upload.failed"));
} }
} }
Boolean validate(final DragAndDropEvent event) { Boolean validate(final DragAndDropEvent event) {
@@ -430,7 +470,7 @@ public class UploadLayout extends VerticalLayout {
} }
void decreaseNumberOfFileUploadsExpected() { void decreaseNumberOfFileUploadsExpected() {
numberOfFileUploadsExpected.decrementAndGet(); artifactUploadState.getNumberOfFileUploadsExpected().decrementAndGet();
} }
List<String> getDuplicateFileNamesList() { List<String> getDuplicateFileNamesList() {
@@ -451,7 +491,7 @@ public class UploadLayout extends VerticalLayout {
void displayDuplicateValidationMessage() { void displayDuplicateValidationMessage() {
// check if streaming of all dropped files are completed // check if streaming of all dropped files are completed
if (numberOfFilesActuallyUpload.intValue() == numberOfFileUploadsExpected.intValue()) { if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() == artifactUploadState.getNumberOfFileUploadsExpected().intValue()) {
displayCompositeMessage(); displayCompositeMessage();
} }
} }
@@ -466,7 +506,6 @@ public class UploadLayout extends VerticalLayout {
} else if (duplicateFileNamesList.size() > 1) { } else if (duplicateFileNamesList.size() > 1) {
message.append(i18n.get("message.no.duplicateFiles")); message.append(i18n.get("message.no.duplicateFiles"));
} }
duplicateFileNamesList.clear();
} }
return message.toString(); return message.toString();
} }
@@ -476,7 +515,7 @@ public class UploadLayout extends VerticalLayout {
} }
void increaseNumberOfFileUploadsExpected() { void increaseNumberOfFileUploadsExpected() {
numberOfFileUploadsExpected.incrementAndGet(); artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet();
} }
void updateFileSize(final String name, final long size) { void updateFileSize(final String name, final long size) {
@@ -495,17 +534,19 @@ public class UploadLayout extends VerticalLayout {
} }
void increaseNumberOfFilesActuallyUpload() { void increaseNumberOfFilesActuallyUpload() {
numberOfFilesActuallyUpload.incrementAndGet(); artifactUploadState.getNumberOfFilesActuallyUpload().incrementAndGet();
} }
/** /**
* Enable process button once upload is completed. * Enable process button once upload is completed.
*/ */
boolean enableProcessBtn() { boolean enableProcessBtn() {
if (numberOfFilesActuallyUpload.intValue() >= numberOfFileUploadsExpected.intValue()) { if (artifactUploadState.getNumberOfFilesActuallyUpload().intValue() >= artifactUploadState
.getNumberOfFileUploadsExpected().intValue()
&& artifactUploadState.getNumberOfFilesActuallyUpload().get() != 0) {
processBtn.setEnabled(true); processBtn.setEnabled(true);
numberOfFileUploadsExpected.set(0); artifactUploadState.getNumberOfFilesActuallyUpload().set(0);
numberOfFilesActuallyUpload.set(0); artifactUploadState.getNumberOfFileUploadsExpected().set(0);
return true; return true;
} }
return false; return false;
@@ -546,8 +587,8 @@ public class UploadLayout extends VerticalLayout {
processBtn.setCaption(SPUILabelDefinitions.PROCESS); processBtn.setCaption(SPUILabelDefinitions.PROCESS);
/* disable when there is no files to upload. */ /* disable when there is no files to upload. */
processBtn.setEnabled(false); processBtn.setEnabled(false);
numberOfFileUploadsExpected.set(0); artifactUploadState.getNumberOfFilesActuallyUpload().set(0);
numberOfFilesActuallyUpload.set(0); artifactUploadState.getNumberOfFileUploadsExpected().set(0);
duplicateFileNamesList.clear(); duplicateFileNamesList.clear();
} }
@@ -623,33 +664,70 @@ public class UploadLayout extends VerticalLayout {
return dropAreaLayout; return dropAreaLayout;
} }
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final UploadArtifactUIEvent event) {
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) {
ui.access(() -> updateActionCount());
} else if (event == UploadArtifactUIEvent.MINIMIZED_STATUS_POPUP) {
ui.access(() -> showUploadStatusButton());
} else if (event == UploadArtifactUIEvent.MAXIMIZED_STATUS_POPUP) {
ui.access(() -> maximizeStatusPopup());
} else if (event == UploadArtifactUIEvent.UPLOAD_FINISHED) {
ui.access(() -> setUploadStatusButtonIconToFinished());
} else if (event == UploadArtifactUIEvent.UPLOAD_STARTED) {
ui.access(() -> setUploadStatusButtonIconToInProgress());
}else if (event == UploadArtifactUIEvent.UPLOAD_STREAMINING_FINISHED) {
//TODO re-check
updateActionCount();
enableProcessBtn();
}
private void onUploadStreamingSuccess(UploadStatusEvent event) {
increaseNumberOfFilesActuallyUpload();
updateActionCount();
enableProcessBtn();
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
}
// display the duplicate message after streaming all files
displayDuplicateValidationMessage();
duplicateFileNamesList.clear();
} }
@PreDestroy private void onUploadStreamingFailure(UploadStatusEvent event) {
void destroy() { onUploadFailure(event);
/* updateActionCount();
* It's good manners to do this, even though vaadin-spring will enableProcessBtn();
* automatically unsubscribe when this UI is garbage collected. // check if we are finished
*/ if (isUploadComplete()) {
eventBus.unsubscribe(this); uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
}
displayDuplicateValidationMessage();
}
private void onUploadSuccess(UploadStatusEvent event) {
updateFileSize(event.getUploadStatus().getFileName(), event.getUploadStatus().getContentLength());
// recorded that we now one more uploaded
increaseNumberOfFilesActuallyUpload();
}
private void onUploadCompletion() {
// check if we are finished
if (isUploadComplete()) {
uploadInfoWindow.uploadSessionFinished();
setUploadStatusButtonIconToFinished();
}
updateActionCount();
enableProcessBtn();
duplicateFileNamesList.clear();
}
private boolean isUploadComplete() {
int uploadedCount = artifactUploadState.getNumberOfFilesActuallyUpload().intValue();
int expectedUploadsCount = artifactUploadState.getNumberOfFileUploadsExpected().intValue();
return uploadedCount == expectedUploadsCount;
}
private void onUploadFailure(final UploadStatusEvent event) {
decreaseNumberOfFileUploadsExpected();
/**
* If upload interrupted because of duplicate file,do not remove the
* file already in upload list
**/
if (getDuplicateFileNamesList().isEmpty()
|| !getDuplicateFileNamesList().contains(event.getUploadStatus().getFileName())) {
final SoftwareModule sw = getSoftwareModuleSelected();
getFileSelected().remove(
new CustomFile(event.getUploadStatus().getFileName(), sw.getName(), sw.getVersion()));
//failed reason to be updated only if there is error other than duplicate file error
uploadInfoWindow.uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus()
.getFailureReason());
}
} }
/** /**
@@ -738,4 +816,5 @@ public class UploadLayout extends VerticalLayout {
uploadStatusButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE); uploadStatusButton.addStyleName(SPUIStyleDefinitions.UPLOAD_PROGRESS_INDICATOR_STYLE);
uploadStatusButton.setIcon(null); uploadStatusButton.setIcon(null);
} }
} }

View File

@@ -11,7 +11,12 @@ package org.eclipse.hawkbit.ui.artifacts.upload;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
@@ -19,6 +24,8 @@ import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
import com.vaadin.data.Container.Indexed; import com.vaadin.data.Container.Indexed;
import com.vaadin.data.Item; import com.vaadin.data.Item;
@@ -69,9 +76,9 @@ public class UploadStatusInfoWindow extends Window {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Grid grid; private Grid grid;
private final IndexedContainer uploads; private IndexedContainer uploads;
private volatile boolean errorOccured = false; private volatile boolean errorOccured = false;
@@ -85,11 +92,14 @@ public class UploadStatusInfoWindow extends Window {
private Button resizeButton; private Button resizeButton;
private UI ui;
/** /**
* Default Constructor. * Default Constructor.
*/ */
UploadStatusInfoWindow() { @PostConstruct
super(); void init() {
setPopupProperties(); setPopupProperties();
createStatusPopupHeaderComponents(); createStatusPopupHeaderComponents();
@@ -106,6 +116,43 @@ public class UploadStatusInfoWindow extends Window {
mainLayout.addComponents(getCaptionLayout(), grid); mainLayout.addComponents(getCaptionLayout(), grid);
mainLayout.setExpandRatio(grid, 1.0F); mainLayout.setExpandRatio(grid, 1.0F);
setContent(mainLayout); setContent(mainLayout);
eventBus.subscribe(this);
ui = UI.getCurrent();
}
@EventBusListenerMethod(scope = EventScope.SESSION)
void onEvent(final UploadStatusEvent event) {
if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_IN_PROGRESS) {
UI.getCurrent().access(
() -> updateProgress(event.getUploadStatus().getFileName(), event.getUploadStatus().getBytesRead(),
event.getUploadStatus().getContentLength()));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STARTED) {
UI.getCurrent().access(() -> onStartOfUpload(event));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FAILED) {
ui.access(() -> uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus()
.getFailureReason()));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_SUCCESSFUL) {
UI.getCurrent().access(() -> uploadSucceeded(event.getUploadStatus().getFileName()));
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FINISHED) {
ui.access(() -> uploadSucceeded(event.getUploadStatus().getFileName()));
}
}
private void onStartOfUpload(UploadStatusEvent event) {
uploadSessionStarted();
uploadStarted(event.getUploadStatus().getFileName());
}
@PreDestroy
void destroy() {
/*
* It's good manners to do this, even though vaadin-spring will
* automatically unsubscribe when this UI is garbage collected.
*/
eventBus.unsubscribe(this);
} }
private void restoreState() { private void restoreState() {
@@ -119,8 +166,10 @@ public class UploadStatusInfoWindow extends Window {
item.getItemProperty(PROGRESS).setValue(statusObject.getProgress()); item.getItemProperty(PROGRESS).setValue(statusObject.getProgress());
item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename()); item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename());
} }
artifactUploadState.setUploadCompleted(true); // artifactUploadState.setUploadCompleted(true);
minimizeButton.setEnabled(false); if (artifactUploadState.isUploadCompleted()) {
minimizeButton.setEnabled(false);
}
} }
} }
@@ -130,6 +179,7 @@ public class UploadStatusInfoWindow extends Window {
setResizable(false); setResizable(false);
setDraggable(true); setDraggable(true);
setClosable(false); setClosable(false);
setModal(true);
} }
private void setGridColumnProperties() { private void setGridColumnProperties() {
@@ -192,6 +242,8 @@ public class UploadStatusInfoWindow extends Window {
private static class StatusRenderer extends HtmlRenderer { private static class StatusRenderer extends HtmlRenderer {
private static final long serialVersionUID = -5365795450234970943L;
@Override @Override
public JsonValue encode(final String value) { public JsonValue encode(final String value) {
String result ; String result ;
@@ -216,18 +268,17 @@ public class UploadStatusInfoWindow extends Window {
void uploadSessionFinished() { void uploadSessionFinished() {
if (!errorOccured) { if (!errorOccured) {
close(); close();
eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_FINISHED);
artifactUploadState.setUploadCompleted(true);
minimizeButton.setEnabled(false);
} }
artifactUploadState.setUploadCompleted(true);
minimizeButton.setEnabled(false);
} }
void uploadSessionStarted() { void uploadSessionStarted() {
close(); if (!artifactUploadState.isStatusPopupMinimized()) {
openWindow(); close();
openWindow();
}
minimizeButton.setEnabled(true); minimizeButton.setEnabled(true);
eventBus.publish(this, UploadArtifactUIEvent.UPLOAD_STARTED);
artifactUploadState.setUploadCompleted(false); artifactUploadState.setUploadCompleted(false);
} }
@@ -287,22 +338,22 @@ public class UploadStatusInfoWindow extends Window {
} }
void uploadFailed(final String filename, final String errorReason) { void uploadFailed(final String filename, final String errorReason) {
if (!errorOccured) {
errorOccured = true;
}
String status = "Failed";
final Item item = uploads.getItem(filename); final Item item = uploads.getItem(filename);
if (item != null) { if (item != null) {
if (!errorOccured) {
errorOccured = true;
}
item.getItemProperty(REASON).setValue(errorReason); item.getItemProperty(REASON).setValue(errorReason);
String status = "Failed";
item.getItemProperty(STATUS).setValue(status); item.getItemProperty(STATUS).setValue(status);
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState }
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename)) List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
.collect(Collectors.toList()); .getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
if (!uploadStatusObjectList.isEmpty()) { .collect(Collectors.toList());
UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0); if (!uploadStatusObjectList.isEmpty()) {
uploadStatusObject.setStatus(status); UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
uploadStatusObject.setReason(errorReason); uploadStatusObject.setStatus(status);
} uploadStatusObject.setReason(errorReason);
} }
} }
@@ -370,4 +421,5 @@ public class UploadStatusInfoWindow extends Window {
closeBtn.addClickListener(event -> clearWindow()); closeBtn.addClickListener(event -> clearWindow());
return closeBtn; return closeBtn;
} }
} }