Java tutorial
/** * 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.management.targettable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.OutputStream; import java.math.BigDecimal; import java.math.RoundingMode; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.ui.common.tagdetails.AbstractTagToken.TagData; import org.eclipse.hawkbit.ui.components.HawkbitErrorNotificationMessage; import org.eclipse.hawkbit.ui.management.event.BulkUploadValidationMessageEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent.TargetComponentEvent; import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.management.state.TargetBulkUpload; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.vaadin.spring.events.EventBus; import com.google.common.base.Splitter; import com.google.common.io.ByteStreams; import com.google.common.io.Files; import com.google.common.io.LineProcessor; import com.vaadin.server.Page; import com.vaadin.ui.Alignment; import com.vaadin.ui.ComboBox; import com.vaadin.ui.CustomComponent; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.ProgressBar; import com.vaadin.ui.TextArea; import com.vaadin.ui.UI; import com.vaadin.ui.Upload; import com.vaadin.ui.Upload.FailedEvent; import com.vaadin.ui.Upload.FailedListener; import com.vaadin.ui.Upload.Receiver; import com.vaadin.ui.Upload.StartedEvent; import com.vaadin.ui.Upload.StartedListener; import com.vaadin.ui.Upload.SucceededEvent; import com.vaadin.ui.Upload.SucceededListener; /** * Bulk target upload handler. */ public class BulkUploadHandler extends CustomComponent implements SucceededListener, FailedListener, Receiver, StartedListener { private static final long serialVersionUID = -1273494705754674501L; private static final Logger LOG = LoggerFactory.getLogger(BulkUploadHandler.class); private static final Splitter SPLITTER = Splitter.on(',').omitEmptyStrings().trimResults(); private final transient TargetManagement targetManagement; private final transient TargetTagManagement tagManagement; private final ComboBox comboBox; private final TextArea descTextArea; private final VaadinMessageSource i18n; private final transient DeploymentManagement deploymentManagement; private final transient DistributionSetManagement distributionSetManagement; private File tempFile; private Upload upload; private final ProgressBar progressBar; private final ManagementUIState managementUIState; private final TargetBulkTokenTags targetBulkTokenTags; private final Label targetsCountLabel; private int successfullTargetCount; private final transient Executor uiExecutor; private final transient EventBus.UIEventBus eventBus; private final transient EntityFactory entityFactory; private final UI uiInstance; BulkUploadHandler(final TargetBulkUpdateWindowLayout targetBulkUpdateWindowLayout, final TargetManagement targetManagement, final TargetTagManagement tagManagement, final EntityFactory entityFactory, final DistributionSetManagement distributionSetManagement, final ManagementUIState managementUIState, final DeploymentManagement deploymentManagement, final VaadinMessageSource i18n, final UI uiInstance, final Executor uiExecutor) { this.uiInstance = uiInstance; this.comboBox = targetBulkUpdateWindowLayout.getDsNamecomboBox(); this.descTextArea = targetBulkUpdateWindowLayout.getDescTextArea(); this.targetManagement = targetManagement; this.progressBar = targetBulkUpdateWindowLayout.getProgressBar(); this.managementUIState = managementUIState; this.deploymentManagement = deploymentManagement; this.targetsCountLabel = targetBulkUpdateWindowLayout.getTargetsCountLabel(); this.targetBulkTokenTags = targetBulkUpdateWindowLayout.getTargetBulkTokenTags(); this.i18n = i18n; this.uiExecutor = uiExecutor; this.eventBus = targetBulkUpdateWindowLayout.getEventBus(); this.distributionSetManagement = distributionSetManagement; this.tagManagement = tagManagement; this.entityFactory = entityFactory; } void buildLayout() { final HorizontalLayout horizontalLayout = new HorizontalLayout(); upload = new Upload(); upload.setEnabled(false); upload.setButtonCaption(i18n.getMessage("caption.bulk.upload")); upload.setReceiver(this); upload.setImmediate(true); upload.setWidthUndefined(); upload.addSucceededListener(this); upload.addFailedListener(this); upload.addStartedListener(this); horizontalLayout.addComponent(upload); horizontalLayout.setComponentAlignment(upload, Alignment.BOTTOM_RIGHT); setCompositionRoot(horizontalLayout); } @Override public OutputStream receiveUpload(final String filename, final String mimeType) { try { tempFile = File.createTempFile("temp", ".csv"); progressBar.setVisible(false); targetsCountLabel.setVisible(false); return new FileOutputStream(tempFile); } catch (final FileNotFoundException e) { LOG.error("File was not found with file name {}", filename, e); } catch (final IOException e) { LOG.error("Error while reading file {}", filename, e); } return ByteStreams.nullOutputStream(); } @Override public void uploadFailed(final FailedEvent event) { LOG.info("Upload failed for file :{} due to {}", event.getFilename(), event.getReason()); } @Override public void uploadSucceeded(final SucceededEvent event) { uiExecutor.execute(new UploadAsync()); } class UploadAsync implements Runnable { @Override public void run() { if (tempFile == null) { return; } try (InputStream tempStream = new FileInputStream(tempFile)) { readFileStream(tempStream); } catch (final FileNotFoundException e) { LOG.error("Temporary file not found with name {}", tempFile.getName(), e); } catch (final IOException e) { LOG.error("Error while opening temorary file ", e); } } private void readFileStream(final InputStream tempStream) { String line; final BigDecimal totalNumberOfLines = getTotalNumberOfLines(); try (final LineNumberReader reader = new LineNumberReader( new InputStreamReader(tempStream, Charset.defaultCharset()))) { LOG.info("Bulk file upload started"); /** * Once control is in upload succeeded method automatically * upload button is re-enabled. To disable the button firing * below event. */ eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_UPLOAD_PROCESS_STARTED)); while ((line = reader.readLine()) != null) { readLine(line, reader.getLineNumber(), totalNumberOfLines); } } catch (final IOException e) { LOG.error("Error reading file {}", tempFile.getName(), e); } catch (final RuntimeException e) { uiInstance.getErrorHandler().error(new ConnectorErrorEvent(uiInstance, e)); } finally { deleteFile(); } syncCountAfterUpload(totalNumberOfLines.intValue()); doAssignments(); eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_UPLOAD_COMPLETED)); // Clearing after assignments are done managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated().clear(); resetSuccessfullTargetCount(); } private void syncCountAfterUpload(final int totalNumberOfLines) { final int syncedFailedTargetCount = totalNumberOfLines - successfullTargetCount; managementUIState.getTargetTableFilters().getBulkUpload() .setSucessfulUploadCount(successfullTargetCount); managementUIState.getTargetTableFilters().getBulkUpload().setFailedUploadCount(syncedFailedTargetCount); managementUIState.getTargetTableFilters().getBulkUpload().setProgressBarCurrentValue(1); eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_TARGET_CREATED)); } private BigDecimal getTotalNumberOfLines() { try { return new BigDecimal( Files.readLines(tempFile, Charset.defaultCharset(), new LineProcessor<Integer>() { private int count; @Override public Integer getResult() { return count; } @Override public boolean processLine(final String line) { count++; return true; } })); } catch (final IOException e) { LOG.error("Error while reading temp file for upload.", e); } return new BigDecimal(0); } private void resetSuccessfullTargetCount() { successfullTargetCount = 0; } private void deleteFile() { if (tempFile.exists()) { final boolean isDeleted = tempFile.delete(); if (!isDeleted) { LOG.info("File {} was not deleted !", tempFile.getName()); } } tempFile = null; } private void readLine(final String line, final int lineNumber, final BigDecimal totalNumberOfLines) { final List<String> targets = SPLITTER.splitToList(line); if (targets.size() == 2) { final String controllerId = targets.get(0); final String targetName = targets.get(1); addNewTarget(controllerId, targetName); } final float previous = managementUIState.getTargetTableFilters().getBulkUpload() .getProgressBarCurrentValue(); final float done = new BigDecimal(lineNumber).divide(totalNumberOfLines, 2, RoundingMode.UP) .floatValue(); if (done > previous) { managementUIState.getTargetTableFilters().getBulkUpload() .setSucessfulUploadCount(successfullTargetCount); managementUIState.getTargetTableFilters().getBulkUpload().setProgressBarCurrentValue(done); eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_TARGET_CREATED)); } } private void doAssignments() { final StringBuilder errorMessage = new StringBuilder(); String dsAssignmentFailedMsg = null; String tagAssignmentFailedMsg = null; if (ifTargetsCreatedSuccessfully()) { if (ifTagsSelected()) { tagAssignmentFailedMsg = tagAssignment(); } if (ifDsSelected()) { dsAssignmentFailedMsg = saveAllAssignments(); } } displayValidationMessage(errorMessage, dsAssignmentFailedMsg, tagAssignmentFailedMsg); } private String saveAllAssignments() { final ActionType actionType = ActionType.FORCED; final long forcedTimeStamp = new Date().getTime(); final TargetBulkUpload targetBulkUpload = managementUIState.getTargetTableFilters().getBulkUpload(); final List<String> targetsList = targetBulkUpload.getTargetsCreated(); final Long dsSelected = (Long) comboBox.getValue(); if (!distributionSetManagement.get(dsSelected).isPresent()) { return i18n.getMessage("message.bulk.upload.assignment.failed"); } deploymentManagement.assignDistributionSet(targetBulkUpload.getDsNameAndVersion(), actionType, forcedTimeStamp, targetsList); return null; } private String tagAssignment() { final Map<Long, TagData> tokensSelected = targetBulkTokenTags.getTokensAdded(); final List<String> deletedTags = new ArrayList<>(); for (final TagData tagData : tokensSelected.values()) { if (!tagManagement.get(tagData.getId()).isPresent()) { deletedTags.add(tagData.getName()); } else { targetManagement.toggleTagAssignment( managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated(), tagData.getName()); } } if (deletedTags.isEmpty()) { return null; } if (deletedTags.size() == 1) { return i18n.getMessage("message.bulk.upload.tag.assignment.failed", deletedTags.get(0)); } return i18n.getMessage("message.bulk.upload.tag.assignments.failed"); } private boolean ifTagsSelected() { return targetBulkTokenTags.getTokenField().getValue() != null; } private boolean ifDsSelected() { return comboBox.getValue() != null; } private boolean ifTargetsCreatedSuccessfully() { return !managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated().isEmpty(); } private void displayValidationMessage(final StringBuilder errorMessage, final String dsAssignmentFailedMsg, final String tagAssignmentFailedMsg) { if (dsAssignmentFailedMsg != null) { errorMessage.append(dsAssignmentFailedMsg); } if (errorMessage.length() > 0) { errorMessage.append("<br>"); } if (tagAssignmentFailedMsg != null) { errorMessage.append(tagAssignmentFailedMsg); } if (errorMessage.length() > 0) { eventBus.publish(this, new BulkUploadValidationMessageEvent(errorMessage.toString())); } } // Exception squid:S1166 - Targets that exist already are simply ignored @SuppressWarnings("squid:S1166") private void addNewTarget(final String controllerId, final String name) { final String newControllerId = controllerId; final String description = descTextArea.getValue(); try { targetManagement.create(entityFactory.target().create().controllerId(newControllerId).name(name) .description(description)); managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated().add(newControllerId); successfullTargetCount++; } catch (final EntityAlreadyExistsException ex) { // Targets that exist already are simply ignored } } } /** * @return the upload */ public Upload getUpload() { return upload; } @Override public void uploadStarted(final StartedEvent event) { if (!event.getFilename().endsWith(".csv")) { new HawkbitErrorNotificationMessage(SPUIStyleDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE, null, i18n.getMessage("bulk.targets.upload"), true).show(Page.getCurrent()); LOG.error("Wrong file format for file {}", event.getFilename()); upload.interruptUpload(); } else { eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_TARGET_UPLOAD_STARTED)); } } }