Merge branch 'master' into Feature/Add_Rest_Api_with_Java_client
Conflicts: examples/hawkbit-example-app/src/main/java/org/eclipse/hawkbit/app/Start.java examples/hawkbit-mgmt-api-client/pom.xml examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/RolloutBuilder.java examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TagBuilder.java examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/ArtifactStoreController.java hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/DataConversionHelper.java hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/RootController.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/UiProperties.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/BaseSwModuleBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleAddUpdateWindow.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadHandler.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableHeader.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/ProxyTarget.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/ManageDistBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CreateOrUpdateFilterHeader.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CreateOrUpdateFilterTable.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterQueryValidation.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/TargetFilterBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/event/CustomFilterUIEvent.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/LoginView.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstag/CreateUpdateDistributionTagLayoutWindow.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstag/DistributionTagButtons.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/tag/CreateUpdateTagLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetAddUpdateWindowLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/CreateUpdateTargetTagLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettag/TargetTagFilterButtons.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/DistributionBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/ProxyRollout.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/ProxyRolloutGroup.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupListGrid.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgroup/RolloutGroupsListHeader.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPDateTimeUtil.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIComponetIdProvider.java hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/common.scss hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/others.scss hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/rollout.scss hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/target-filter-query.scss hawkbit-ui/src/main/resources/messages.properties hawkbit-ui/src/main/resources/messages_de.properties hawkbit-ui/src/main/resources/messages_en.properties Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
@@ -22,14 +22,17 @@ import org.springframework.context.annotation.Import;
|
||||
@SpringBootApplication
|
||||
@Import({ RepositoryApplicationConfiguration.class })
|
||||
@EnableHawkbitManagedSecurityConfiguration
|
||||
// Exception squid:S1118 - Spring boot standard behavior
|
||||
@SuppressWarnings({ "squid:S1118" })
|
||||
public class Start {
|
||||
|
||||
/**
|
||||
* Main method to start the spring-boot application.
|
||||
*
|
||||
* @param args
|
||||
* the VM arguments.
|
||||
*/
|
||||
// Exception squid:S2095 - Spring boot standard behavior
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
public static void main(final String[] args) {
|
||||
SpringApplication.run(Start.class, args);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
@@ -9,7 +8,8 @@
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
@@ -133,13 +133,17 @@
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-bom</artifactId>
|
||||
<version>7.6.3</version>
|
||||
<version>${vaadin.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||
|
||||
/**
|
||||
* The bean of a simulated device which can be stored in the
|
||||
* {@link DeviceSimulatorRepository} or shown in the UI.
|
||||
@@ -22,16 +24,15 @@ public abstract class AbstractSimulatedDevice {
|
||||
private Status status;
|
||||
private double progress;
|
||||
private String swversion = "unknown";
|
||||
private ResponseStatus responseStatus = ResponseStatus.SUCCESSFUL;
|
||||
private UpdateStatus updateStatus = new UpdateStatus(ResponseStatus.SUCCESSFUL, "Simulation complete!");
|
||||
private Protocol protocol = Protocol.DMF_AMQP;
|
||||
private String targetSecurityToken;
|
||||
|
||||
private int nextPollCounterSec;
|
||||
|
||||
/**
|
||||
* Enum definition of the protocol to be used for the simulated device.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
public enum Protocol {
|
||||
/**
|
||||
@@ -69,24 +70,6 @@ public abstract class AbstractSimulatedDevice {
|
||||
ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* The status to response to the hawkbit update server if an simulated
|
||||
* update process should be respond with successful or failure update.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
public enum ResponseStatus {
|
||||
/**
|
||||
* updated has been successful and response the successful update.
|
||||
*/
|
||||
SUCCESSFUL,
|
||||
/**
|
||||
* updated has been not successful and response the error update.
|
||||
*/
|
||||
ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* empty constructor.
|
||||
*/
|
||||
@@ -158,12 +141,12 @@ public abstract class AbstractSimulatedDevice {
|
||||
this.swversion = swversion;
|
||||
}
|
||||
|
||||
public ResponseStatus getResponseStatus() {
|
||||
return responseStatus;
|
||||
public UpdateStatus getUpdateStatus() {
|
||||
return updateStatus;
|
||||
}
|
||||
|
||||
public void setResponseStatus(final ResponseStatus responseStatus) {
|
||||
this.responseStatus = responseStatus;
|
||||
public void setUpdateStatus(final UpdateStatus updateStatus) {
|
||||
this.updateStatus = updateStatus;
|
||||
}
|
||||
|
||||
public Protocol getProtocol() {
|
||||
@@ -177,4 +160,13 @@ public abstract class AbstractSimulatedDevice {
|
||||
public void setNextPollCounterSec(final int nextPollDelayInSec) {
|
||||
this.nextPollCounterSec = nextPollDelayInSec;
|
||||
}
|
||||
|
||||
public String getTargetSecurityToken() {
|
||||
return targetSecurityToken;
|
||||
}
|
||||
|
||||
public void setTargetSecurityToken(final String targetSecurityToken) {
|
||||
this.targetSecurityToken = targetSecurityToken;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.http.ControllerResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -18,7 +16,7 @@ import com.jayway.jsonpath.JsonPath;
|
||||
import com.jayway.jsonpath.PathNotFoundException;
|
||||
|
||||
/**
|
||||
* @author Michael Hirsch
|
||||
* A simulated device using the DDI API of the hawkBit update server.
|
||||
*
|
||||
*/
|
||||
public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
@@ -26,12 +24,12 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DDISimulatedDevice.class);
|
||||
|
||||
private final int pollDelaySec;
|
||||
private final ScheduledExecutorService pollthreadpool;
|
||||
private final ControllerResource controllerResource;
|
||||
|
||||
private final DeviceSimulatorUpdater deviceUpdater;
|
||||
|
||||
private volatile boolean removed;
|
||||
private volatile Long currentActionId;
|
||||
private final DeviceSimulatorUpdater deviceUpdater;
|
||||
|
||||
/**
|
||||
* @param id
|
||||
@@ -42,18 +40,14 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
* the delay of the poll interval in sec
|
||||
* @param controllerResource
|
||||
* the http controller resource
|
||||
* @param pollthreadpool
|
||||
* the threadpool for polling endpoint
|
||||
* @param deviceUpdater
|
||||
* the service to update devices
|
||||
*/
|
||||
public DDISimulatedDevice(final String id, final String tenant, final int pollDelaySec,
|
||||
final ControllerResource controllerResource, final ScheduledExecutorService pollthreadpool,
|
||||
final DeviceSimulatorUpdater deviceUpdater) {
|
||||
final ControllerResource controllerResource, final DeviceSimulatorUpdater deviceUpdater) {
|
||||
super(id, tenant, Protocol.DDI_HTTP);
|
||||
this.pollDelaySec = pollDelaySec;
|
||||
this.controllerResource = controllerResource;
|
||||
this.pollthreadpool = pollthreadpool;
|
||||
this.deviceUpdater = deviceUpdater;
|
||||
setNextPollCounterSec(pollDelaySec);
|
||||
}
|
||||
@@ -76,27 +70,12 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
final String basePollJson = controllerResource.get(getTenant(), getId());
|
||||
try {
|
||||
final String href = JsonPath.parse(basePollJson).read("_links.deploymentBase.href");
|
||||
final long actionId = Long.parseLong(href.substring(href.lastIndexOf("/") + 1, href.indexOf("?")));
|
||||
final long actionId = Long.parseLong(href.substring(href.lastIndexOf('/') + 1, href.indexOf('?')));
|
||||
if (currentActionId == null) {
|
||||
final String deploymentJson = controllerResource.getDeployment(getTenant(), getId(), actionId);
|
||||
final String swVersion = JsonPath.parse(deploymentJson).read("deployment.chunks[0].version");
|
||||
currentActionId = actionId;
|
||||
deviceUpdater.startUpdate(getTenant(), getId(), actionId, swVersion, (device, actionId1) -> {
|
||||
switch (device.getResponseStatus()) {
|
||||
case SUCCESSFUL:
|
||||
controllerResource.postSuccessFeedback(getTenant(), getId(),
|
||||
actionId1);
|
||||
break;
|
||||
case ERROR:
|
||||
controllerResource.postErrorFeedback(getTenant(), getId(),
|
||||
actionId1);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException(
|
||||
"simulated device has an unknown response status + " + device.getResponseStatus());
|
||||
}
|
||||
currentActionId = null;
|
||||
});
|
||||
startDdiUpdate(actionId, swVersion);
|
||||
}
|
||||
} catch (final PathNotFoundException e) {
|
||||
// href might not be in the json response, so ignore
|
||||
@@ -106,4 +85,21 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void startDdiUpdate(final long actionId, final String swVersion) {
|
||||
deviceUpdater.startUpdate(getTenant(), getId(), actionId, swVersion, null, null, (device, actionId1) -> {
|
||||
switch (device.getUpdateStatus().getResponseStatus()) {
|
||||
case SUCCESSFUL:
|
||||
controllerResource.postSuccessFeedback(getTenant(), getId(), actionId1);
|
||||
break;
|
||||
case ERROR:
|
||||
controllerResource.postErrorFeedback(getTenant(), getId(), actionId1);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("simulated device has an unknown response status + "
|
||||
+ device.getUpdateStatus().getResponseStatus());
|
||||
}
|
||||
currentActionId = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
/**
|
||||
* An simulated device using the DMF API of the hawkbit update server.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
* A simulated device using the DMF API of the hawkBit update server.
|
||||
*/
|
||||
public class DMFSimulatedDevice extends AbstractSimulatedDevice {
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@ import com.vaadin.spring.annotation.EnableVaadin;
|
||||
/**
|
||||
* The main-method to start the Spring-Boot application.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableVaadin
|
||||
@@ -46,6 +44,8 @@ public class DeviceSimulator {
|
||||
* @param args
|
||||
* the args
|
||||
*/
|
||||
// Exception squid:S2095 - Spring boot standard behavior
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
public static void main(final String[] args) {
|
||||
SpringApplication.run(DeviceSimulator.class, args);
|
||||
}
|
||||
|
||||
@@ -8,27 +8,56 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||
import org.eclipse.hawkbit.dmf.json.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
/**
|
||||
* @author Michael Hirsch
|
||||
* Update simulation handler.
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class DeviceSimulatorUpdater {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class);
|
||||
|
||||
private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(4);
|
||||
|
||||
@@ -54,14 +83,18 @@ public class DeviceSimulatorUpdater {
|
||||
* @param actionId
|
||||
* the actionId from the hawkbit update server to start the
|
||||
* update.
|
||||
* @param swVersion
|
||||
* @param modules
|
||||
* the software module version from the hawkbit update server
|
||||
* @param swVersion
|
||||
* the software version as static value in case modules is null
|
||||
* @param targetSecurityToken
|
||||
* the target security token for download authentication
|
||||
* @param callback
|
||||
* the callback which gets called when the simulated update
|
||||
* process has been finished
|
||||
*/
|
||||
public void startUpdate(final String tenant, final String id, final long actionId, final String swVersion,
|
||||
final UpdaterCallback callback) {
|
||||
final List<SoftwareModule> modules, final String targetSecurityToken, final UpdaterCallback callback) {
|
||||
AbstractSimulatedDevice device = repository.get(tenant, id);
|
||||
|
||||
// plug and play - non existing device will be auto created
|
||||
@@ -70,14 +103,23 @@ public class DeviceSimulatorUpdater {
|
||||
}
|
||||
|
||||
device.setProgress(0.0);
|
||||
device.setSwversion(swVersion);
|
||||
|
||||
if (modules == null || modules.isEmpty()) {
|
||||
device.setSwversion(swVersion);
|
||||
} else {
|
||||
device.setSwversion(modules.stream().map(sm -> sm.getModuleVersion()).collect(Collectors.joining(", ")));
|
||||
}
|
||||
device.setTargetSecurityToken(targetSecurityToken);
|
||||
eventbus.post(new InitUpdate(device));
|
||||
|
||||
threadPool.schedule(new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback),
|
||||
2_000, TimeUnit.MILLISECONDS);
|
||||
threadPool.schedule(
|
||||
new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback, modules), 2_000,
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private static final class DeviceSimulatorUpdateThread implements Runnable {
|
||||
private static final int MINIMUM_TOKENLENGTH_FOR_HINT = 6;
|
||||
|
||||
private static final Random rndSleep = new SecureRandom();
|
||||
|
||||
private final AbstractSimulatedDevice device;
|
||||
@@ -85,38 +127,205 @@ public class DeviceSimulatorUpdater {
|
||||
private final long actionId;
|
||||
private final EventBus eventbus;
|
||||
private final UpdaterCallback callback;
|
||||
private final List<SoftwareModule> modules;
|
||||
|
||||
private DeviceSimulatorUpdateThread(final AbstractSimulatedDevice device, final SpSenderService spSenderService,
|
||||
final long actionId, final EventBus eventbus, final UpdaterCallback callback) {
|
||||
final long actionId, final EventBus eventbus, final UpdaterCallback callback,
|
||||
final List<SoftwareModule> modules) {
|
||||
this.device = device;
|
||||
this.spSenderService = spSenderService;
|
||||
this.actionId = actionId;
|
||||
this.eventbus = eventbus;
|
||||
this.callback = callback;
|
||||
this.modules = modules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (device.getProgress() <= 0 && modules != null) {
|
||||
device.setUpdateStatus(simulateDownloads(device.getTargetSecurityToken()));
|
||||
if (isErrorResponse(device.getUpdateStatus())) {
|
||||
callback.updateFinished(device, actionId);
|
||||
eventbus.post(new ProgressUpdate(device));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final double newProgress = device.getProgress() + 0.2;
|
||||
device.setProgress(newProgress);
|
||||
if (newProgress < 1.0) {
|
||||
threadPool.schedule(
|
||||
new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback),
|
||||
new DeviceSimulatorUpdateThread(device, spSenderService, actionId, eventbus, callback, modules),
|
||||
rndSleep.nextInt(5_000), TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
callback.updateFinished(device, actionId);
|
||||
}
|
||||
eventbus.post(new ProgressUpdate(device));
|
||||
}
|
||||
|
||||
private UpdateStatus simulateDownloads(final String targetToken) {
|
||||
final List<UpdateStatus> status = new ArrayList<>();
|
||||
|
||||
LOGGER.info("Simulate downloads for {}", device.getId());
|
||||
|
||||
modules.forEach(module -> module.getArtifacts()
|
||||
.forEach(artifact -> handleArtifacts(targetToken, status, artifact)));
|
||||
|
||||
final UpdateStatus result = new UpdateStatus(ResponseStatus.SUCCESSFUL);
|
||||
result.getStatusMessages().add("Simulation complete!");
|
||||
status.forEach(download -> {
|
||||
result.getStatusMessages().addAll(download.getStatusMessages());
|
||||
if (isErrorResponse(download)) {
|
||||
result.setResponseStatus(ResponseStatus.ERROR);
|
||||
}
|
||||
});
|
||||
|
||||
LOGGER.info("Download simulations complete for {}", device.getId());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isErrorResponse(final UpdateStatus status) {
|
||||
if (status == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ResponseStatus.ERROR.equals(status.getResponseStatus());
|
||||
}
|
||||
|
||||
private static void handleArtifacts(final String targetToken, final List<UpdateStatus> status,
|
||||
final Artifact artifact) {
|
||||
artifact.getUrls().entrySet().forEach(entry -> {
|
||||
switch (entry.getKey()) {
|
||||
case HTTP:
|
||||
case HTTPS:
|
||||
status.add(downloadUrl(entry.getValue(), targetToken, artifact.getHashes().getSha1(),
|
||||
artifact.getSize()));
|
||||
break;
|
||||
default:
|
||||
// not supported yet
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static UpdateStatus downloadUrl(final String url, final String targetToken, final String sha1Hash,
|
||||
final long size) {
|
||||
LOGGER.debug("Downloading {} with token {}, expected sha1 hash {} and size {}", url,
|
||||
hideTokenDetails(targetToken), sha1Hash, size);
|
||||
|
||||
long overallread = 0;
|
||||
try {
|
||||
final CloseableHttpClient httpclient = createHttpClientThatAcceptsAllServerCerts();
|
||||
final HttpGet request = new HttpGet(url);
|
||||
request.addHeader(HttpHeaders.AUTHORIZATION, "TargetToken " + targetToken);
|
||||
|
||||
final String sha1HashResult;
|
||||
try (final CloseableHttpResponse response = httpclient.execute(request)) {
|
||||
|
||||
if (response.getStatusLine().getStatusCode() != HttpStatus.OK.value()) {
|
||||
final String message = wrongStatusCode(url, response);
|
||||
return new UpdateStatus(ResponseStatus.ERROR, message);
|
||||
}
|
||||
|
||||
if (response.getEntity().getContentLength() != size) {
|
||||
final String message = wrongContentLength(url, size, response);
|
||||
return new UpdateStatus(ResponseStatus.ERROR, message);
|
||||
}
|
||||
|
||||
final File tempFile = File.createTempFile("uploadFile", null);
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
|
||||
try (final DigestOutputStream dos = new DigestOutputStream(new FileOutputStream(tempFile), md)) {
|
||||
try (final BufferedOutputStream bdos = new BufferedOutputStream(dos)) {
|
||||
try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) {
|
||||
overallread = ByteStreams.copy(bis, bdos);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (tempFile != null && !tempFile.delete()) {
|
||||
LOGGER.error("Could not delete temporary file: {}", tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (overallread != size) {
|
||||
final String message = incompleteRead(url, size, overallread);
|
||||
return new UpdateStatus(ResponseStatus.ERROR, message);
|
||||
}
|
||||
|
||||
sha1HashResult = BaseEncoding.base16().lowerCase().encode(md.digest());
|
||||
}
|
||||
|
||||
if (!sha1Hash.equalsIgnoreCase(sha1HashResult)) {
|
||||
final String message = wrongHash(url, sha1Hash, overallread, sha1HashResult);
|
||||
return new UpdateStatus(ResponseStatus.ERROR, message);
|
||||
}
|
||||
|
||||
} catch (IOException | KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||
LOGGER.error("Failed to download {} with {}", url, e.getMessage());
|
||||
return new UpdateStatus(ResponseStatus.ERROR, "Failed to download " + url + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
final String message = "Downloaded " + url + " (" + overallread + " bytes)";
|
||||
LOGGER.debug(message);
|
||||
return new UpdateStatus(ResponseStatus.SUCCESSFUL, message);
|
||||
}
|
||||
|
||||
private static String hideTokenDetails(final String targetToken) {
|
||||
if (targetToken.isEmpty()) {
|
||||
return "<EMTPTY!>";
|
||||
}
|
||||
|
||||
if (targetToken.length() <= MINIMUM_TOKENLENGTH_FOR_HINT) {
|
||||
return "***";
|
||||
}
|
||||
|
||||
return targetToken.substring(0, 2) + "***"
|
||||
+ targetToken.substring(targetToken.length() - 2, targetToken.length());
|
||||
}
|
||||
|
||||
private static String wrongHash(final String url, final String sha1Hash, final long overallread,
|
||||
final String sha1HashResult) {
|
||||
final String message = "Download " + url + " failed with SHA1 hash missmatch (Expected: " + sha1Hash
|
||||
+ " but got: " + sha1HashResult + ") (" + overallread + " bytes)";
|
||||
LOGGER.error(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
private static String incompleteRead(final String url, final long size, final long overallread) {
|
||||
final String message = "Download " + url + " is incomplete (Expected: " + size + " but got: " + overallread
|
||||
+ ")";
|
||||
LOGGER.error(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
private static String wrongContentLength(final String url, final long size,
|
||||
final CloseableHttpResponse response) {
|
||||
final String message = "Download " + url + " has wrong content length (Expected: " + size + " but got: "
|
||||
+ response.getEntity().getContentLength() + ")";
|
||||
LOGGER.error(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
private static String wrongStatusCode(final String url, final CloseableHttpResponse response) {
|
||||
final String message = "Download " + url + " failed (" + response.getStatusLine().getStatusCode() + ")";
|
||||
LOGGER.error(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
private static CloseableHttpClient createHttpClientThatAcceptsAllServerCerts()
|
||||
throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||
final SSLContextBuilder builder = new SSLContextBuilder();
|
||||
builder.loadTrustMaterial(null, (chain, authType) -> true);
|
||||
final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
|
||||
return HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback interface which is called when the simulated update process has
|
||||
* been finished and the caller of starting the simulated update process can
|
||||
* send the result to the hawkbit update server back.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
* send the result back to the hawkBit update server.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface UpdaterCallback {
|
||||
|
||||
@@ -26,9 +26,6 @@ import com.google.common.eventbus.EventBus;
|
||||
/**
|
||||
* Poll time trigger which executes the {@link DDISimulatedDevice#poll()} every
|
||||
* second.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class NextPollTimeController {
|
||||
@@ -59,16 +56,15 @@ public class NextPollTimeController {
|
||||
|
||||
devices.forEach(device -> {
|
||||
int nextCounter = device.getNextPollCounterSec() - 1;
|
||||
if (nextCounter < 0) {
|
||||
if (device instanceof DDISimulatedDevice) {
|
||||
try {
|
||||
pollService.submit(() -> ((DDISimulatedDevice) device).poll());
|
||||
} catch (final IllegalStateException e) {
|
||||
LOGGER.trace("Device could not be polled", e);
|
||||
}
|
||||
nextCounter = ((DDISimulatedDevice) device).getPollDelaySec();
|
||||
if (nextCounter < 0 && device instanceof DDISimulatedDevice) {
|
||||
try {
|
||||
pollService.submit(() -> ((DDISimulatedDevice) device).poll());
|
||||
} catch (final IllegalStateException e) {
|
||||
LOGGER.trace("Device could not be polled", e);
|
||||
}
|
||||
nextCounter = ((DDISimulatedDevice) device).getPollDelaySec();
|
||||
}
|
||||
|
||||
device.setNextPollCounterSec(nextCounter);
|
||||
});
|
||||
eventBus.post(new NextPollCounterUpdate(devices));
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.http.ControllerResource;
|
||||
@@ -24,15 +22,9 @@ import feign.Logger;
|
||||
/**
|
||||
* The simulated device factory to create either {@link DMFSimulatedDevice} or
|
||||
* {@link DDISimulatedDevice#}.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class SimulatedDeviceFactory {
|
||||
|
||||
private static final ScheduledExecutorService pollThreadPool = Executors.newScheduledThreadPool(4);
|
||||
|
||||
@Autowired
|
||||
private DeviceSimulatorUpdater deviceUpdater;
|
||||
|
||||
@@ -47,7 +39,8 @@ public class SimulatedDeviceFactory {
|
||||
* the protocol of the device
|
||||
* @return the created simulated device
|
||||
*/
|
||||
public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant, final Protocol protocol) {
|
||||
public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant,
|
||||
final Protocol protocol) {
|
||||
return createSimulatedDevice(id, tenant, protocol, 30, null, null);
|
||||
}
|
||||
|
||||
@@ -80,7 +73,7 @@ public class SimulatedDeviceFactory {
|
||||
final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger())
|
||||
.requestInterceptor(new GatewayTokenInterceptor(gatewayToken)).logLevel(Logger.Level.BASIC)
|
||||
.target(ControllerResource.class, baseEndpoint.toString());
|
||||
return new DDISimulatedDevice(id, tenant, pollDelaySec, controllerResource, pollThreadPool, deviceUpdater);
|
||||
return new DDISimulatedDevice(id, tenant, pollDelaySec, controllerResource, deviceUpdater);
|
||||
default:
|
||||
throw new IllegalArgumentException("Protocol " + protocol + " unknown");
|
||||
}
|
||||
|
||||
@@ -86,7 +86,10 @@ public class SimulationController {
|
||||
final String deviceId = name + i;
|
||||
repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint),
|
||||
gatewayToken));
|
||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
||||
|
||||
if (protocol == Protocol.DMF_AMQP) {
|
||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseEntity.ok("Updated " + amount + " DMF connected targets!");
|
||||
|
||||
@@ -11,10 +11,12 @@ package org.eclipse.hawkbit.simulator;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -24,6 +26,7 @@ import org.springframework.stereotype.Component;
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@ConditionalOnProperty(prefix = "hawkbit.device.simulator", name = "autostart", matchIfMissing = true)
|
||||
public class SimulatorStartup implements ApplicationListener<ContextRefreshedEvent> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SimulatorStartup.class);
|
||||
|
||||
@@ -52,7 +55,9 @@ public class SimulatorStartup implements ApplicationListener<ContextRefreshedEve
|
||||
LOGGER.error("Creation of simulated device at startup failed.", e);
|
||||
}
|
||||
|
||||
spSenderService.createOrUpdateThing(autostart.getTenant(), deviceId);
|
||||
if (autostart.getApi() == Protocol.DMF_AMQP) {
|
||||
spSenderService.createOrUpdateThing(autostart.getTenant(), deviceId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 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.simulator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Update status of the simulated update.
|
||||
*
|
||||
*/
|
||||
public class UpdateStatus {
|
||||
private ResponseStatus responseStatus;
|
||||
private List<String> statusMessages;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param responseStatus
|
||||
* of the update
|
||||
*/
|
||||
public UpdateStatus(final ResponseStatus responseStatus) {
|
||||
this.responseStatus = responseStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor including status message.
|
||||
*
|
||||
* @param responseStatus
|
||||
* of the update
|
||||
* @param message
|
||||
* of the update status
|
||||
*/
|
||||
public UpdateStatus(final ResponseStatus responseStatus, final String message) {
|
||||
this(responseStatus);
|
||||
statusMessages = new ArrayList<>();
|
||||
statusMessages.add(message);
|
||||
}
|
||||
|
||||
public ResponseStatus getResponseStatus() {
|
||||
return responseStatus;
|
||||
}
|
||||
|
||||
public void setResponseStatus(final ResponseStatus responseStatus) {
|
||||
this.responseStatus = responseStatus;
|
||||
}
|
||||
|
||||
public List<String> getStatusMessages() {
|
||||
if (statusMessages == null) {
|
||||
statusMessages = new ArrayList<>();
|
||||
}
|
||||
|
||||
return statusMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* The status to response to the hawkBit update server if an simulated
|
||||
* update process should be respond with successful or failure update.
|
||||
*/
|
||||
public enum ResponseStatus {
|
||||
/**
|
||||
* Update has been successful and response the successful update.
|
||||
*/
|
||||
SUCCESSFUL,
|
||||
|
||||
/**
|
||||
* Update has been not successful and response the error update.
|
||||
*/
|
||||
ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,6 +39,12 @@ public class AmqpProperties {
|
||||
*/
|
||||
private String deadLetterExchange = "simulator.deadletter";
|
||||
|
||||
/**
|
||||
* Message time to live (ttl) for the deadletter queue. Default ttl is 1
|
||||
* hour.
|
||||
*/
|
||||
private int deadLetterTtl = 60_000;
|
||||
|
||||
public String getReceiverConnectorQueueFromSp() {
|
||||
return receiverConnectorQueueFromSp;
|
||||
}
|
||||
@@ -70,4 +76,12 @@ public class AmqpProperties {
|
||||
public void setSenderForSpExchange(final String senderForSpExchange) {
|
||||
this.senderForSpExchange = senderForSpExchange;
|
||||
}
|
||||
|
||||
public int getDeadLetterTtl() {
|
||||
return deadLetterTtl;
|
||||
}
|
||||
|
||||
public void setDeadLetterTtl(final int deadLetterTtl) {
|
||||
this.deadLetterTtl = deadLetterTtl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.handler.annotation.Header;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Handle all incoming Messages from hawkBit update server.
|
||||
*
|
||||
@@ -88,6 +90,8 @@ public class SpReceiverService extends ReceiverService {
|
||||
if (eventHeader == null) {
|
||||
logAndThrowMessageError(message, "Event Topic is not set");
|
||||
}
|
||||
// Exception squid:S2259 - Checked before
|
||||
@SuppressWarnings({ "squid:S2259" })
|
||||
final EventTopic eventTopic = EventTopic.valueOf(eventHeader.toString());
|
||||
switch (eventTopic) {
|
||||
case DOWNLOAD_AND_INSTALL:
|
||||
@@ -109,7 +113,7 @@ public class SpReceiverService extends ReceiverService {
|
||||
final Long actionId = convertMessage(message, Long.class);
|
||||
|
||||
final SimulatedUpdate update = new SimulatedUpdate(tenant, thingId, actionId);
|
||||
spSenderService.finishUpdateProcess(update, "Simulation canceled");
|
||||
spSenderService.finishUpdateProcess(update, Lists.newArrayList("Simulation canceled"));
|
||||
}
|
||||
|
||||
private void handleUpdateProcess(final Message message, final String thingId) {
|
||||
@@ -120,19 +124,20 @@ public class SpReceiverService extends ReceiverService {
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(message,
|
||||
DownloadAndUpdateRequest.class);
|
||||
final Long actionId = downloadAndUpdateRequest.getActionId();
|
||||
final String targetSecurityToken = downloadAndUpdateRequest.getTargetSecurityToken();
|
||||
|
||||
deviceUpdater.startUpdate(tenant, thingId, actionId,
|
||||
downloadAndUpdateRequest.getSoftwareModules().get(0).getModuleVersion(), (device, actionId1) -> {
|
||||
switch (device.getResponseStatus()) {
|
||||
deviceUpdater.startUpdate(tenant, thingId, actionId, null, downloadAndUpdateRequest.getSoftwareModules(),
|
||||
targetSecurityToken, (device, actionId1) -> {
|
||||
switch (device.getUpdateStatus().getResponseStatus()) {
|
||||
case SUCCESSFUL:
|
||||
spSenderService.finishUpdateProcess(
|
||||
new SimulatedUpdate(device.getTenant(), device.getId(), actionId1),
|
||||
"Simulation complete!");
|
||||
device.getUpdateStatus().getStatusMessages());
|
||||
break;
|
||||
case ERROR:
|
||||
spSenderService.finishUpdateProcessWithError(
|
||||
new SimulatedUpdate(device.getTenant(), device.getId(), actionId1),
|
||||
"Simulation complete with error!");
|
||||
device.getUpdateStatus().getStatusMessages());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.amqp;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
|
||||
@@ -23,13 +24,9 @@ import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Sender service to send message to SP.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Sender service to send messages to update server.
|
||||
*/
|
||||
@Service
|
||||
public class SpSenderService extends SenderService {
|
||||
@@ -59,8 +56,9 @@ public class SpSenderService extends SenderService {
|
||||
* @param description
|
||||
* a description according the update process
|
||||
*/
|
||||
public void finishUpdateProcess(final SimulatedUpdate update, final String description) {
|
||||
final Message updateResultMessage = createUpdateResultMessage(update, ActionStatus.FINISHED, description);
|
||||
public void finishUpdateProcess(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||
final Message updateResultMessage = createUpdateResultMessage(update, ActionStatus.FINISHED,
|
||||
updateResultMessages);
|
||||
sendMessage(spExchange, updateResultMessage);
|
||||
}
|
||||
|
||||
@@ -72,9 +70,9 @@ public class SpSenderService extends SenderService {
|
||||
* @param messageDescription
|
||||
* a description according the update process
|
||||
*/
|
||||
public void finishUpdateProcessWithError(final SimulatedUpdate update, final String messageDescription) {
|
||||
sendErrorgMessage(update, messageDescription);
|
||||
LOGGER.debug("Update process finished with error \"{}\" reported by thing {}", messageDescription,
|
||||
public void finishUpdateProcessWithError(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||
sendErrorgMessage(update, updateResultMessages);
|
||||
LOGGER.debug("Update process finished with error \"{}\" reported by thing {}", updateResultMessages,
|
||||
update.getThingId());
|
||||
}
|
||||
|
||||
@@ -88,8 +86,8 @@ public class SpSenderService extends SenderService {
|
||||
* @param actionId
|
||||
* the ID of the action for the error message
|
||||
*/
|
||||
public void sendErrorMessage(final String tenant, final String messageDescription, final Long actionId) {
|
||||
final Message message = createActionStatusMessage(tenant, ActionStatus.ERROR, messageDescription, actionId);
|
||||
public void sendErrorMessage(final String tenant, final List<String> updateResultMessages, final Long actionId) {
|
||||
final Message message = createActionStatusMessage(tenant, ActionStatus.ERROR, updateResultMessages, actionId);
|
||||
sendMessage(spExchange, message);
|
||||
}
|
||||
|
||||
@@ -101,8 +99,8 @@ public class SpSenderService extends SenderService {
|
||||
* @param warningMessage
|
||||
* a warning description
|
||||
*/
|
||||
public void sendWarningMessage(final SimulatedUpdate update, final String warningMessage) {
|
||||
final Message message = createActionStatusMessage(update, warningMessage, ActionStatus.WARNING);
|
||||
public void sendWarningMessage(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||
final Message message = createActionStatusMessage(update, updateResultMessages, ActionStatus.WARNING);
|
||||
sendMessage(spExchange, message);
|
||||
}
|
||||
|
||||
@@ -119,8 +117,8 @@ public class SpSenderService extends SenderService {
|
||||
* the cached value
|
||||
*/
|
||||
public void sendActionStatusMessage(final String tenant, final ActionStatus actionStatus,
|
||||
final String actionMessage, final Long actionId) {
|
||||
final Message message = createActionStatusMessage(tenant, actionStatus, actionMessage, actionId);
|
||||
final List<String> updateResultMessages, final Long actionId) {
|
||||
final Message message = createActionStatusMessage(tenant, actionStatus, updateResultMessages, actionId);
|
||||
sendMessage(message);
|
||||
|
||||
}
|
||||
@@ -162,11 +160,11 @@ public class SpSenderService extends SenderService {
|
||||
*
|
||||
* @param context
|
||||
* the current context
|
||||
* @param messageDescription
|
||||
* a description according the update process
|
||||
* @param updateResultMessages
|
||||
* a list of descriptions according the update process
|
||||
*/
|
||||
private void sendErrorgMessage(final SimulatedUpdate update, final String messageDescription) {
|
||||
final Message message = createActionStatusMessage(update, messageDescription, ActionStatus.ERROR);
|
||||
private void sendErrorgMessage(final SimulatedUpdate update, final List<String> updateResultMessages) {
|
||||
final Message message = createActionStatusMessage(update, updateResultMessages, ActionStatus.ERROR);
|
||||
sendMessage(spExchange, message);
|
||||
}
|
||||
|
||||
@@ -183,7 +181,7 @@ public class SpSenderService extends SenderService {
|
||||
* the cacheValue value
|
||||
*/
|
||||
private Message createActionStatusMessage(final String tenant, final ActionStatus actionStatus,
|
||||
final String actionMessage, final Long actionId) {
|
||||
final List<String> updateResultMessages, final Long actionId) {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
final Map<String, Object> headers = messageProperties.getHeaders();
|
||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||
@@ -192,15 +190,14 @@ public class SpSenderService extends SenderService {
|
||||
headers.put(MessageHeaderKey.TENANT, tenant);
|
||||
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
||||
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
|
||||
if (!StringUtils.isEmpty(actionMessage)) {
|
||||
actionUpdateStatus.getMessage().add(actionMessage);
|
||||
}
|
||||
actionUpdateStatus.getMessage().addAll(updateResultMessages);
|
||||
|
||||
actionUpdateStatus.setActionId(actionId);
|
||||
return convertMessage(actionUpdateStatus, messageProperties);
|
||||
}
|
||||
|
||||
private Message createUpdateResultMessage(final SimulatedUpdate cacheValue, final ActionStatus actionStatus,
|
||||
final String updateResultMessage) {
|
||||
final List<String> updateResultMessages) {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
final Map<String, Object> headers = messageProperties.getHeaders();
|
||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||
@@ -209,14 +206,14 @@ public class SpSenderService extends SenderService {
|
||||
headers.put(MessageHeaderKey.TENANT, cacheValue.getTenant());
|
||||
headers.put(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
||||
headers.put(MessageHeaderKey.CONTENT_TYPE, MessageProperties.CONTENT_TYPE_JSON);
|
||||
actionUpdateStatus.getMessage().add(updateResultMessage);
|
||||
actionUpdateStatus.getMessage().addAll(updateResultMessages);
|
||||
actionUpdateStatus.setActionId(cacheValue.getActionId());
|
||||
return convertMessage(actionUpdateStatus, messageProperties);
|
||||
}
|
||||
|
||||
private Message createActionStatusMessage(final SimulatedUpdate update, final String messageDescription,
|
||||
private Message createActionStatusMessage(final SimulatedUpdate update, final List<String> updateResultMessages,
|
||||
final ActionStatus status) {
|
||||
return createActionStatusMessage(update.getTenant(), status, messageDescription, update.getActionId());
|
||||
return createActionStatusMessage(update.getTenant(), status, updateResultMessages, update.getActionId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||
/**
|
||||
* Event definition object which is published if the simulated device updated
|
||||
* its update progress.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
public class ProgressUpdate {
|
||||
|
||||
@@ -8,21 +8,19 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.ui;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.ResponseStatus;
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Status;
|
||||
import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
|
||||
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
|
||||
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
||||
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
||||
import org.eclipse.hawkbit.simulator.ui.GenerateDialog.GenerateDialogCallback;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -52,13 +50,27 @@ import com.vaadin.ui.renderers.ProgressBarRenderer;
|
||||
* Vaadin view which allows to generate devices through the DMF API and show the
|
||||
* current simulated devices in a grid with their current status and update
|
||||
* progress.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
@SpringView(name = "")
|
||||
public class SimulatorView extends VerticalLayout implements View {
|
||||
|
||||
private static final String NEXT_POLL_COUNTER_SEC_COL = "nextPollCounterSec";
|
||||
|
||||
private static final String RESPONSE_STATUS_COL = "responseStatus";
|
||||
|
||||
private static final String PROTOCOL_COL = "protocol";
|
||||
|
||||
private static final String TENANT_COL = "tenant";
|
||||
|
||||
private static final String PROGRESS_COL = "progress";
|
||||
|
||||
private static final String SWVERSION_COL = "swversion";
|
||||
|
||||
private static final String STATUS_COL = "status";
|
||||
|
||||
private static final String ID_COL = "id";
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Autowired
|
||||
@@ -79,6 +91,7 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
|
||||
private BeanContainer<String, AbstractSimulatedDevice> beanContainer;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void enter(final ViewChangeEvent event) {
|
||||
eventbus.register(this);
|
||||
@@ -91,7 +104,7 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
createToolbar();
|
||||
|
||||
beanContainer = new BeanContainer<>(AbstractSimulatedDevice.class);
|
||||
beanContainer.setBeanIdProperty("id");
|
||||
beanContainer.setBeanIdProperty(ID_COL);
|
||||
|
||||
grid.setSizeFull();
|
||||
grid.setCellStyleGenerator(new CellStyleGenerator() {
|
||||
@@ -100,28 +113,28 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
|
||||
@Override
|
||||
public String getStyle(final CellReference cellReference) {
|
||||
return cellReference.getPropertyId().equals("status") ? "centeralign" : null;
|
||||
return cellReference.getPropertyId().equals(STATUS_COL) ? "centeralign" : null;
|
||||
}
|
||||
});
|
||||
|
||||
grid.setSelectionMode(SelectionMode.NONE);
|
||||
grid.setContainerDataSource(beanContainer);
|
||||
grid.appendHeaderRow().getCell("responseStatus").setComponent(responseComboBox);
|
||||
grid.setColumnOrder("id", "status", "swversion", "progress", "tenant", "protocol", "responseStatus",
|
||||
"nextPollCounterSec");
|
||||
grid.appendHeaderRow().getCell(RESPONSE_STATUS_COL).setComponent(responseComboBox);
|
||||
grid.setColumnOrder(ID_COL, STATUS_COL, SWVERSION_COL, PROGRESS_COL, TENANT_COL, PROTOCOL_COL,
|
||||
RESPONSE_STATUS_COL, NEXT_POLL_COUNTER_SEC_COL);
|
||||
// header widths
|
||||
grid.getColumn("status").setMaximumWidth(80);
|
||||
grid.getColumn("protocol").setMaximumWidth(180);
|
||||
grid.getColumn("responseStatus").setMaximumWidth(240);
|
||||
grid.getColumn("nextPollCounterSec").setMaximumWidth(210);
|
||||
grid.getColumn(STATUS_COL).setMaximumWidth(80);
|
||||
grid.getColumn(PROTOCOL_COL).setMaximumWidth(180);
|
||||
grid.getColumn(RESPONSE_STATUS_COL).setMaximumWidth(240);
|
||||
grid.getColumn(NEXT_POLL_COUNTER_SEC_COL).setMaximumWidth(210);
|
||||
|
||||
grid.getColumn("nextPollCounterSec").setHeaderCaption("Next Poll in (sec)");
|
||||
grid.getColumn("swversion").setHeaderCaption("SW Version");
|
||||
grid.getColumn("responseStatus").setHeaderCaption("Response Update Status");
|
||||
grid.getColumn("progress").setRenderer(new ProgressBarRenderer());
|
||||
grid.getColumn("protocol").setConverter(createProtocolConverter());
|
||||
grid.getColumn("status").setRenderer(new HtmlRenderer(), createStatusConverter());
|
||||
grid.removeColumn("tenant");
|
||||
grid.getColumn(NEXT_POLL_COUNTER_SEC_COL).setHeaderCaption("Next Poll in (sec)");
|
||||
grid.getColumn(SWVERSION_COL).setHeaderCaption("SW Version");
|
||||
grid.getColumn(RESPONSE_STATUS_COL).setHeaderCaption("Response Update Status");
|
||||
grid.getColumn(PROGRESS_COL).setRenderer(new ProgressBarRenderer());
|
||||
grid.getColumn(PROTOCOL_COL).setConverter(createProtocolConverter());
|
||||
grid.getColumn(STATUS_COL).setRenderer(new HtmlRenderer(), createStatusConverter());
|
||||
grid.removeColumn(TENANT_COL);
|
||||
|
||||
// grid combobox
|
||||
responseComboBox.setItemIcon(ResponseStatus.SUCCESSFUL, FontAwesome.CHECK_CIRCLE);
|
||||
@@ -129,8 +142,8 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
responseComboBox.setNullSelectionAllowed(false);
|
||||
responseComboBox.setValue(ResponseStatus.SUCCESSFUL);
|
||||
responseComboBox.addValueChangeListener(valueChangeEvent -> {
|
||||
beanContainer.getItemIds().forEach(itemId -> beanContainer.getItem(itemId).getItemProperty("responseStatus")
|
||||
.setValue(valueChangeEvent.getProperty().getValue()));
|
||||
beanContainer.getItemIds().forEach(itemId -> beanContainer.getItem(itemId)
|
||||
.getItemProperty(RESPONSE_STATUS_COL).setValue(valueChangeEvent.getProperty().getValue()));
|
||||
});
|
||||
|
||||
// add all components
|
||||
@@ -141,7 +154,7 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
setExpandRatio(grid, 1.0F);
|
||||
|
||||
// load beans
|
||||
repository.getAll().forEach(device -> beanContainer.addBean(device));
|
||||
repository.getAll().forEach(beanContainer::addBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,21 +163,16 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
eventbus.unregister(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Subscribe
|
||||
public void pollCounterUpdate(final NextPollCounterUpdate update) {
|
||||
final List<AbstractSimulatedDevice> devices = update.getDevices();
|
||||
this.getUI().access(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
devices.forEach(device -> {
|
||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||
if (item != null) {
|
||||
item.getItemProperty("nextPollCounterSec").setValue(device.getNextPollCounterSec());
|
||||
}
|
||||
});
|
||||
this.getUI().access(() -> devices.forEach(device -> {
|
||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||
if (item != null) {
|
||||
item.getItemProperty(NEXT_POLL_COUNTER_SEC_COL).setValue(device.getNextPollCounterSec());
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,21 +181,19 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
* @param update
|
||||
* the update event posted on the event bus
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Subscribe
|
||||
public void initUpdate(final InitUpdate update) {
|
||||
final AbstractSimulatedDevice device = update.getDevice();
|
||||
this.getUI().access(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||
if (item != null) {
|
||||
item.getItemProperty("progress").setValue(device.getProgress());
|
||||
item.getItemProperty("status").setValue(Status.PEDNING);
|
||||
item.getItemProperty("swversion").setValue(device.getSwversion());
|
||||
}
|
||||
|
||||
this.getUI().access(() -> {
|
||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
item.getItemProperty(PROGRESS_COL).setValue(device.getProgress());
|
||||
item.getItemProperty(STATUS_COL).setValue(Status.PEDNING);
|
||||
item.getItemProperty(SWVERSION_COL).setValue(device.getSwversion());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -197,35 +203,37 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
* @param update
|
||||
* the update event posted on the event bus
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Subscribe
|
||||
public void progessUpdate(final ProgressUpdate update) {
|
||||
final AbstractSimulatedDevice device = update.getDevice();
|
||||
this.getUI().access(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||
if (item != null) {
|
||||
item.getItemProperty("progress").setValue(device.getProgress());
|
||||
if (device.getProgress() >= 1) {
|
||||
switch (device.getResponseStatus()) {
|
||||
case SUCCESSFUL:
|
||||
item.getItemProperty("status").setValue(Status.FINISH);
|
||||
break;
|
||||
case ERROR:
|
||||
item.getItemProperty("status").setValue(Status.ERROR);
|
||||
break;
|
||||
default:
|
||||
item.getItemProperty("status").setValue(Status.UNKNWON);
|
||||
}
|
||||
} else {
|
||||
item.getItemProperty("status").setValue(Status.PEDNING);
|
||||
}
|
||||
}
|
||||
|
||||
this.getUI().access(() -> {
|
||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||
if (item != null) {
|
||||
item.getItemProperty(PROGRESS_COL).setValue(device.getProgress());
|
||||
setStatusColumn(device, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void setStatusColumn(final AbstractSimulatedDevice device, final BeanItem<AbstractSimulatedDevice> item) {
|
||||
if (device.getProgress() >= 1) {
|
||||
switch (device.getUpdateStatus().getResponseStatus()) {
|
||||
case SUCCESSFUL:
|
||||
item.getItemProperty(STATUS_COL).setValue(Status.FINISH);
|
||||
break;
|
||||
case ERROR:
|
||||
item.getItemProperty(STATUS_COL).setValue(Status.ERROR);
|
||||
break;
|
||||
default:
|
||||
item.getItemProperty(STATUS_COL).setValue(Status.UNKNWON);
|
||||
}
|
||||
} else {
|
||||
item.getItemProperty(STATUS_COL).setValue(Status.PEDNING);
|
||||
}
|
||||
}
|
||||
|
||||
private void createToolbar() {
|
||||
final Button createDevicesButton = new Button("generate...");
|
||||
createDevicesButton.setIcon(FontAwesome.GEARS);
|
||||
@@ -246,18 +254,15 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
}
|
||||
|
||||
private void openGenerateDialog() {
|
||||
UI.getCurrent().addWindow(new GenerateDialog(new GenerateDialogCallback() {
|
||||
@Override
|
||||
public void okButton(final String namePrefix, final String tenant, final int amount, final int pollDelay,
|
||||
final URL basePollUrl, final String gatewayToken, final Protocol protocol) {
|
||||
for (int index = 0; index < amount; index++) {
|
||||
final String deviceId = namePrefix + index;
|
||||
beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId,
|
||||
tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken)));
|
||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
||||
}
|
||||
}
|
||||
}));
|
||||
UI.getCurrent().addWindow(
|
||||
new GenerateDialog((namePrefix, tenant, amount, pollDelay, basePollUrl, gatewayToken, protocol) -> {
|
||||
for (int index = 0; index < amount; index++) {
|
||||
final String deviceId = namePrefix + index;
|
||||
beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId,
|
||||
tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken)));
|
||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private Converter<String, Protocol> createProtocolConverter() {
|
||||
|
||||
@@ -4,16 +4,20 @@ The hawkBit example application is a standalone spring-boot application with an
|
||||
We have have described several options for you to get access to the example.
|
||||
|
||||
## Try out the example application in our hawkBit sandbox on Bluemix
|
||||
- try out Management UI https://hawkbit.eu-gb.mybluemix.net/UI
|
||||
- try out Management API https://hawkbit.eu-gb.mybluemix.net/rest/v1/targets (don't forget basic auth header)
|
||||
- try out DDI API https://hawkbit.eu-gb.mybluemix.net/DEFAULT/controller/v1/MYTESTDEVICE
|
||||
- try out Management UI https://hawkbit.eu-gb.mybluemix.net/UI (username: admin, passwd: admin)
|
||||
- try out Management API https://hawkbit.eu-gb.mybluemix.net/rest/v1/targets (don't forget basic auth header; username: admin, passwd: admin)
|
||||
- try out DDI API https://hawkbit.eu-gb.mybluemix.net/DEFAULT/controller/v1/MYTESTDEVICE (authentication disabled)
|
||||
|
||||
## On your own workstation
|
||||
### Run
|
||||
```
|
||||
java -jar examples/hawkbit-example-app/target/hawkbit-example-app-*-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
_(Note: you have to add the JDBC driver also to your class path if you intend to use another database than H2.)_
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
run org eclipse.hawkbit.app.Start
|
||||
```
|
||||
|
||||
@@ -20,11 +20,11 @@ import com.vaadin.spring.annotation.SpringUI;
|
||||
* login path. The easiest way to get an hawkBit login UI running is to extend
|
||||
* the {@link HawkbitLoginUI} and to annotated it with {@link SpringUI} as in
|
||||
* this example to the defined {@link HawkbitTheme#LOGIN_UI_PATH}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SpringUI(path = HawkbitTheme.LOGIN_UI_PATH)
|
||||
// Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from
|
||||
// Vaadin.
|
||||
@SuppressWarnings({ "squid:MaximumInheritanceDepth" })
|
||||
public class MyLoginUI extends HawkbitLoginUI {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -29,6 +29,9 @@ import com.vaadin.spring.annotation.SpringUI;
|
||||
*/
|
||||
@SpringUI
|
||||
@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET)
|
||||
// Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from
|
||||
// Vaadin.
|
||||
@SuppressWarnings({ "squid:MaximumInheritanceDepth" })
|
||||
public class MyUI extends HawkbitUI {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -38,6 +38,8 @@ public class Start {
|
||||
* @param args
|
||||
* the VM arguments.
|
||||
*/
|
||||
// Exception squid:S2095 - Spring boot standard behavior
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
public static void main(final String[] args) {
|
||||
SpringApplication.run(Start.class, args);
|
||||
}
|
||||
|
||||
@@ -8,3 +8,9 @@
|
||||
#
|
||||
|
||||
vaadin.servlet.productionMode=true
|
||||
|
||||
hawkbit.artifact.url.coap.enabled=false
|
||||
hawkbit.artifact.url.http.enabled=false
|
||||
hawkbit.artifact.url.https.enabled=true
|
||||
hawkbit.artifact.url.https.pattern={protocol}://{hostname}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}
|
||||
hawkbit.artifact.url.https.hostname=hawkbit.eu-gb.mybluemix.net
|
||||
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# This profile adds basic configurations for a MySQL DB usage.
|
||||
# Keep in mind that you need the MariaDB driver in your classpath on compile.
|
||||
# see https://github.com/eclipse/hawkbit/wiki/Run-hawkBit
|
||||
|
||||
spring.jpa.database=MYSQL
|
||||
spring.datasource.url=jdbc:mysql://localhost:3306/hawkbit
|
||||
spring.datasource.username=root
|
||||
spring.datasource.password=
|
||||
spring.datasource.driverClassName=org.mariadb.jdbc.Driver
|
||||
|
||||
spring.datasource.max-active=100
|
||||
spring.datasource.max-idle=10
|
||||
spring.datasource.min-idle=10
|
||||
spring.datasource.initial-size=10
|
||||
spring.datasource.validation-query=select 1 from dual
|
||||
spring.datasource.validation-interval=30000
|
||||
spring.datasource.test-on-borrow=true
|
||||
spring.datasource.test-on-return=false
|
||||
spring.datasource.test-while-idle=true
|
||||
spring.datasource.time-between-eviction-runs-millis=30000
|
||||
spring.datasource.min-evictable-idle-time-millis=60000
|
||||
spring.datasource.max-wait=10000
|
||||
spring.datasource.jmx-enabled=true
|
||||
@@ -7,21 +7,28 @@
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
# DDI authentication configuration
|
||||
hawkbit.server.ddi.security.authentication.anonymous.enabled=true
|
||||
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
|
||||
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
|
||||
hawkbit.server.ddi.security.authentication.targettoken.enabled=true
|
||||
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=true
|
||||
|
||||
spring.profiles.active=amqp
|
||||
# Download URL generation config
|
||||
hawkbit.artifact.url.coap.enabled=false
|
||||
hawkbit.artifact.url.http.enabled=true
|
||||
hawkbit.artifact.url.http.port=8080
|
||||
hawkbit.artifact.url.https.enabled=false
|
||||
|
||||
## Vaadin configuration
|
||||
vaadin.servlet.productionMode=false
|
||||
|
||||
## Configuration for RabbitMQ integration
|
||||
## Configuration for DMF/RabbitMQ integration
|
||||
spring.profiles.active=amqp
|
||||
spring.rabbitmq.username=guest
|
||||
spring.rabbitmq.password=guest
|
||||
spring.rabbitmq.virtualHost=/
|
||||
spring.rabbitmq.host=localhost
|
||||
spring.rabbitmq.port=5672
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter_ttl
|
||||
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
|
||||
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
|
||||
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.artifact.repository;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -122,7 +125,11 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
LOGGER.debug("storing file {} of content {}", filename, contentType);
|
||||
tempFile = File.createTempFile("uploadFile", null);
|
||||
try (final FileOutputStream os = new FileOutputStream(tempFile)) {
|
||||
return store(content, contentType, os, tempFile, hash);
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(os)) {
|
||||
try (BufferedInputStream bis = new BufferedInputStream(content)) {
|
||||
return store(content, contentType, bos, tempFile, hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final IOException | MongoException e1) {
|
||||
throw new ArtifactStoreException(e1.getMessage(), e1);
|
||||
@@ -162,7 +169,7 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
|
||||
}
|
||||
|
||||
private DbArtifact store(final InputStream content, final String contentType, final FileOutputStream os,
|
||||
private DbArtifact store(final InputStream content, final String contentType, final OutputStream os,
|
||||
final File tempFile, final DbArtifactHash hash) {
|
||||
final GridFsArtifact storedArtifact;
|
||||
try {
|
||||
@@ -185,7 +192,8 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
throw new ArtifactStoreException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (hash != null && hash.getMd5() != null && !storedArtifact.getHashes().getMd5().equals(hash.getMd5())) {
|
||||
if (hash != null && hash.getMd5() != null
|
||||
&& !storedArtifact.getHashes().getMd5().equalsIgnoreCase(hash.getMd5())) {
|
||||
throw new HashNotMatchException("The given md5 hash " + hash.getMd5()
|
||||
+ " not matching the calculated md5 hash " + storedArtifact.getHashes().getMd5(),
|
||||
HashNotMatchException.MD5);
|
||||
@@ -195,14 +203,14 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
|
||||
}
|
||||
|
||||
private static String computeSHA1Hash(final InputStream stream, final FileOutputStream os,
|
||||
final String providedSHA1Sum) throws NoSuchAlgorithmException, IOException {
|
||||
private static String computeSHA1Hash(final InputStream stream, final OutputStream os, final String providedSHA1Sum)
|
||||
throws NoSuchAlgorithmException, IOException {
|
||||
String sha1Hash;
|
||||
// compute digest
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
final DigestOutputStream dos = new DigestOutputStream(os, md);
|
||||
ByteStreams.copy(stream, dos);
|
||||
dos.close();
|
||||
try (final DigestOutputStream dos = new DigestOutputStream(os, md)) {
|
||||
ByteStreams.copy(stream, dos);
|
||||
}
|
||||
sha1Hash = BaseEncoding.base16().lowerCase().encode(md.digest());
|
||||
if (providedSHA1Sum != null && !providedSHA1Sum.equalsIgnoreCase(sha1Hash)) {
|
||||
throw new HashNotMatchException(
|
||||
|
||||
@@ -71,6 +71,8 @@ public class MongoConfiguration extends AbstractMongoConfiguration {
|
||||
@Override
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
// Closed by pre-destroy
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
public Mongo mongo() throws UnknownHostException {
|
||||
final MongoClientURI uri = new MongoClientURI(properties.getUri(), createBuilderOutOfOptions(options));
|
||||
|
||||
|
||||
@@ -42,6 +42,6 @@ hawkbit.controller.minPollingTime=00:00:30
|
||||
|
||||
|
||||
# Configuration for RabbitMQ integration
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter_ttl
|
||||
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
|
||||
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
|
||||
3
hawkbit-core/README.md
Normal file
3
hawkbit-core/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# hawkBit Core
|
||||
|
||||
Various internal interfaces and utility classes.
|
||||
@@ -22,11 +22,10 @@ import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
* This resource bundles using specified basenames, to resource loading. This
|
||||
* MessageSource implementation supports more than 1 properties file with the
|
||||
* same name. All properties files will be merged.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DistributedResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {
|
||||
// Exception squid:S2387 - Follows our upper case convention
|
||||
@SuppressWarnings({ "squid:S2387" })
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DistributedResourceBundleMessageSource.class);
|
||||
private static final String PROPERTIES_SUFFIX = ".properties";
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@@ -13,7 +13,6 @@ package org.eclipse.hawkbit.api;
|
||||
* URLs to specific artifacts.
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ArtifactUrlHandler {
|
||||
|
||||
/**
|
||||
@@ -34,4 +33,11 @@ public interface ArtifactUrlHandler {
|
||||
*/
|
||||
String getUrl(String controllerId, final Long softwareModuleId, final String filename, final String sha1Hash,
|
||||
final UrlProtocol protocol);
|
||||
|
||||
/**
|
||||
* @param protocol
|
||||
* to check support for
|
||||
* @return <code>true</code> of the handler supports given protocol.
|
||||
*/
|
||||
boolean protocolSupported(UrlProtocol protocol);
|
||||
}
|
||||
|
||||
@@ -79,6 +79,12 @@ public class ArtifactUrlHandlerProperties {
|
||||
* @return the pattern to build the URL.
|
||||
*/
|
||||
String getPattern();
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if the {@link ProtocolProperties} is
|
||||
* enabled.
|
||||
*/
|
||||
boolean isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,6 +100,20 @@ public class ArtifactUrlHandlerProperties {
|
||||
*/
|
||||
private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}";
|
||||
|
||||
/**
|
||||
* Enables HTTP URI generation in DDI and DMF.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
@@ -144,6 +164,20 @@ public class ArtifactUrlHandlerProperties {
|
||||
*/
|
||||
private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}";
|
||||
|
||||
/**
|
||||
* Enables HTTPS URI generation in DDI and DMF.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
@@ -194,6 +228,20 @@ public class ArtifactUrlHandlerProperties {
|
||||
*/
|
||||
private String pattern = "{protocol}://{ip}:{port}/fw/{tenant}/{targetId}/sha1/{artifactSHA1}";
|
||||
|
||||
/**
|
||||
* Enables CoAP URI generation in DMF.
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHostname() {
|
||||
return hostname;
|
||||
|
||||
@@ -84,4 +84,15 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
|
||||
return replaceMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean protocolSupported(final UrlProtocol protocol) {
|
||||
final String protocolString = protocol.name().toLowerCase();
|
||||
final ProtocolProperties properties = urlHandlerProperties.getProperties(protocolString);
|
||||
if (properties == null || properties.getPattern() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return properties.isEnabled();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ public class TenantConfigurationPollingDurationValidator implements TenantConfig
|
||||
}
|
||||
|
||||
@Override
|
||||
// Exception squid:S1166 - Hide origin exception
|
||||
@SuppressWarnings({ "squid:S1166" })
|
||||
public void validate(final Object tenantConfigurationObject) {
|
||||
TenantConfigurationValidator.super.validate(tenantConfigurationObject);
|
||||
final String tenantConfigurationString = (String) tenantConfigurationObject;
|
||||
|
||||
@@ -145,9 +145,11 @@ public class DdiArtifactStoreController implements DdiDlArtifactStoreControllerR
|
||||
actionStatus.setStatus(Status.DOWNLOAD);
|
||||
|
||||
if (range != null) {
|
||||
actionStatus.addMessage("It is a partial download request: " + range);
|
||||
actionStatus.addMessage(ControllerManagement.SERVER_MESSAGE_PREFIX + "Target downloads range " + range
|
||||
+ " of: " + request.getRequestURI());
|
||||
} else {
|
||||
actionStatus.addMessage("Target downloads");
|
||||
actionStatus.addMessage(
|
||||
ControllerManagement.SERVER_MESSAGE_PREFIX + "Target downloads: " + request.getRequestURI());
|
||||
}
|
||||
controllerManagement.addActionStatusMessage(actionStatus);
|
||||
return action;
|
||||
|
||||
@@ -182,9 +182,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
statusMessage.setStatus(Status.DOWNLOAD);
|
||||
|
||||
if (range != null) {
|
||||
statusMessage.addMessage("It is a partial download request: " + range);
|
||||
statusMessage.addMessage(ControllerManagement.SERVER_MESSAGE_PREFIX + "Target downloads range " + range
|
||||
+ " of: " + request.getRequestURI());
|
||||
} else {
|
||||
statusMessage.addMessage("Controller downloads");
|
||||
statusMessage.addMessage(
|
||||
ControllerManagement.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI());
|
||||
}
|
||||
controllerManagement.addActionStatusMessage(statusMessage);
|
||||
return action;
|
||||
@@ -304,13 +306,13 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
LOG.debug("Controller confirmed cancel (actionid: {}, targetid: {}) as we got {} report.", actionid,
|
||||
targetid, feedback.getStatus().getExecution());
|
||||
actionStatus.setStatus(Status.CANCELED);
|
||||
actionStatus.addMessage("Controller confirmed cancelation");
|
||||
actionStatus.addMessage(ControllerManagement.SERVER_MESSAGE_PREFIX + "Target confirmed cancelation.");
|
||||
break;
|
||||
case REJECTED:
|
||||
LOG.info("Controller reported internal error (actionid: {}, targetid: {}) as we got {} report.", actionid,
|
||||
targetid, feedback.getStatus().getExecution());
|
||||
actionStatus.setStatus(Status.WARNING);
|
||||
actionStatus.addMessage("Controller reported internal ERROR and REJECTED update.");
|
||||
actionStatus.addMessage(ControllerManagement.SERVER_MESSAGE_PREFIX + "Target REJECTED update.");
|
||||
break;
|
||||
case CLOSED:
|
||||
handleClosedUpdateStatus(feedback, targetid, actionid, actionStatus);
|
||||
@@ -337,7 +339,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
LOG.debug("Controller reported intermediate status (actionid: {}, targetid: {}) as we got {} report.", actionid,
|
||||
targetid, feedback.getStatus().getExecution());
|
||||
actionStatus.setStatus(Status.RUNNING);
|
||||
actionStatus.addMessage("Controller reported: " + feedback.getStatus().getExecution());
|
||||
actionStatus.addMessage(
|
||||
ControllerManagement.SERVER_MESSAGE_PREFIX + "Target reported " + feedback.getStatus().getExecution());
|
||||
}
|
||||
|
||||
private static void handleClosedUpdateStatus(final DdiActionFeedback feedback, final String targetid,
|
||||
@@ -346,10 +349,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
feedback.getStatus().getExecution());
|
||||
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
|
||||
actionStatus.setStatus(Status.ERROR);
|
||||
actionStatus.addMessage("Controller reported CLOSED with ERROR!");
|
||||
actionStatus.addMessage(ControllerManagement.SERVER_MESSAGE_PREFIX + "Target reported CLOSED with ERROR!");
|
||||
} else {
|
||||
actionStatus.setStatus(Status.FINISHED);
|
||||
actionStatus.addMessage("Controller reported CLOSED with OK!");
|
||||
actionStatus.addMessage(ControllerManagement.SERVER_MESSAGE_PREFIX + "Target reported CLOSED with OK!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,8 +390,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
LOG.debug("Found an active CancelAction for target {}. returning cancel: {}", targetid, cancel);
|
||||
|
||||
controllerManagement.registerRetrieved(action,
|
||||
"Controller retrieved cancel action and should start now the cancelation.");
|
||||
controllerManagement.registerRetrieved(action, ControllerManagement.SERVER_MESSAGE_PREFIX
|
||||
+ "Target retrieved cancel action and should start now the cancelation.");
|
||||
|
||||
return new ResponseEntity<>(cancel, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.amqp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
|
||||
import org.springframework.amqp.core.Binding;
|
||||
import org.springframework.amqp.core.BindingBuilder;
|
||||
@@ -18,6 +15,7 @@ import org.springframework.amqp.core.FanoutExchange;
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitAdmin;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
@@ -31,15 +29,31 @@ import org.springframework.context.annotation.Bean;
|
||||
* {@code amqp} to use a AMQP for communication with SP enabled devices.
|
||||
*
|
||||
*/
|
||||
@EnableConfigurationProperties(AmqpProperties.class)
|
||||
@EnableConfigurationProperties({ AmqpProperties.class, AmqpDeadletterProperties.class })
|
||||
public class AmqpConfiguration {
|
||||
|
||||
@Autowired
|
||||
protected AmqpProperties amqpProperties;
|
||||
|
||||
@Autowired
|
||||
protected AmqpDeadletterProperties amqpDeadletterProperties;
|
||||
|
||||
@Autowired
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
/**
|
||||
* Create a {@link RabbitAdmin} and ignore declaration exceptions.
|
||||
* {@link RabbitAdmin#setIgnoreDeclarationExceptions(boolean)}
|
||||
*
|
||||
* @return the bean
|
||||
*/
|
||||
@Bean
|
||||
public RabbitAdmin rabbitAdmin() {
|
||||
final RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
|
||||
rabbitAdmin.setIgnoreDeclarationExceptions(true);
|
||||
return rabbitAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set the Jackson2JsonMessageConverter.
|
||||
*
|
||||
@@ -59,7 +73,8 @@ public class AmqpConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public Queue receiverQueue() {
|
||||
return new Queue(amqpProperties.getReceiverQueue(), true, false, false, getDeadLetterExchangeArgs());
|
||||
return new Queue(amqpProperties.getReceiverQueue(), true, false, false,
|
||||
amqpDeadletterProperties.getDeadLetterExchangeArgs(amqpProperties.getDeadLetterExchange()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +94,7 @@ public class AmqpConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public Queue deadLetterQueue() {
|
||||
return new Queue(amqpProperties.getDeadLetterQueue());
|
||||
return amqpDeadletterProperties.createDeadletterQueue(amqpProperties.getDeadLetterQueue());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,10 +164,4 @@ public class AmqpConfiguration {
|
||||
return containerFactory;
|
||||
}
|
||||
|
||||
private Map<String, Object> getDeadLetterExchangeArgs() {
|
||||
final Map<String, Object> args = new HashMap<>();
|
||||
args.put("x-dead-letter-exchange", amqpProperties.getDeadLetterExchange());
|
||||
return args;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.security.CoapAnonymousPreAuthenticatedFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticateSecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedAnonymousDownload;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedAnonymousFilter;
|
||||
@@ -97,7 +96,6 @@ public class AmqpControllerAuthentfication {
|
||||
filterChain.add(anonymousDownloadFilter);
|
||||
|
||||
filterChain.add(new ControllerPreAuthenticatedAnonymousFilter(ddiSecruityProperties));
|
||||
filterChain.add(new CoapAnonymousPreAuthenticatedFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 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.amqp;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Bean which holds the necessary properties for configuring the AMQP deadletter
|
||||
* queue.
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.dmf.rabbitmq.deadLetter")
|
||||
public class AmqpDeadletterProperties {
|
||||
|
||||
/**
|
||||
* Message time to live (ttl) for the deadletter queue. Default ttl is 3
|
||||
* weeks.
|
||||
*/
|
||||
private long ttl = Duration.ofDays(21).toMillis();
|
||||
|
||||
/**
|
||||
* Return the deadletter arguments.
|
||||
*
|
||||
* @param exchange
|
||||
* the deadletter exchange
|
||||
* @return map which holds the properties
|
||||
*/
|
||||
public Map<String, Object> getDeadLetterExchangeArgs(final String exchange) {
|
||||
final Map<String, Object> args = new HashMap<>();
|
||||
args.put("x-dead-letter-exchange", exchange);
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deadletter queue with ttl for messages
|
||||
*
|
||||
* @param queueName
|
||||
* the deadlette queue name
|
||||
* @return the deadletter queue
|
||||
*/
|
||||
public Queue createDeadletterQueue(final String queueName) {
|
||||
return new Queue(queueName, true, false, false, getTTLArgs());
|
||||
}
|
||||
|
||||
private Map<String, Object> getTTLArgs() {
|
||||
final Map<String, Object> args = new HashMap<>();
|
||||
args.put("x-message-ttl", getTtl());
|
||||
return args;
|
||||
}
|
||||
|
||||
public long getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
public void setTtl(final long ttl) {
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -82,6 +82,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
.getSoftwareModules();
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = new DownloadAndUpdateRequest();
|
||||
downloadAndUpdateRequest.setActionId(targetAssignDistributionSetEvent.getActionId());
|
||||
downloadAndUpdateRequest.setTargetSecurityToken(targetAssignDistributionSetEvent.getTargetToken());
|
||||
|
||||
for (final org.eclipse.hawkbit.repository.model.SoftwareModule softwareModule : modules) {
|
||||
final SoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(controllerId, softwareModule);
|
||||
@@ -154,18 +155,26 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
private Artifact convertArtifact(final String targetId, final LocalArtifact localArtifact) {
|
||||
final Artifact artifact = new Artifact();
|
||||
|
||||
artifact.getUrls().put(Artifact.UrlProtocol.COAP,
|
||||
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.COAP));
|
||||
artifact.getUrls().put(Artifact.UrlProtocol.HTTP,
|
||||
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.HTTP));
|
||||
artifact.getUrls().put(Artifact.UrlProtocol.HTTPS,
|
||||
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.HTTPS));
|
||||
if (artifactUrlHandler.protocolSupported(UrlProtocol.COAP)) {
|
||||
artifact.getUrls().put(Artifact.UrlProtocol.COAP,
|
||||
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.COAP));
|
||||
}
|
||||
|
||||
if (artifactUrlHandler.protocolSupported(UrlProtocol.HTTP)) {
|
||||
artifact.getUrls().put(Artifact.UrlProtocol.HTTP,
|
||||
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.HTTP));
|
||||
}
|
||||
|
||||
if (artifactUrlHandler.protocolSupported(UrlProtocol.HTTPS)) {
|
||||
artifact.getUrls().put(Artifact.UrlProtocol.HTTPS,
|
||||
artifactUrlHandler.getUrl(targetId, localArtifact.getSoftwareModule().getId(),
|
||||
localArtifact.getFilename(), localArtifact.getSha1Hash(), UrlProtocol.HTTPS));
|
||||
}
|
||||
|
||||
artifact.setFilename(localArtifact.getFilename());
|
||||
artifact.setHashes(new ArtifactHash(localArtifact.getSha1Hash(), null));
|
||||
artifact.setHashes(new ArtifactHash(localArtifact.getSha1Hash(), localArtifact.getMd5Hash()));
|
||||
artifact.setSize(localArtifact.getSize());
|
||||
return artifact;
|
||||
}
|
||||
|
||||
@@ -305,7 +305,8 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
final List<SoftwareModule> softwareModuleList = controllerManagement
|
||||
.findSoftwareModulesByDistributionSet(distributionSet);
|
||||
eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(),
|
||||
target.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress()));
|
||||
target.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress(),
|
||||
target.getSecurityToken()));
|
||||
|
||||
}
|
||||
|
||||
@@ -336,9 +337,8 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
final Action action = checkActionExist(message, actionUpdateStatus);
|
||||
|
||||
final ActionStatus actionStatus = new ActionStatus();
|
||||
final List<String> messageText = actionUpdateStatus.getMessage();
|
||||
final String messageString = String.join(", ", messageText);
|
||||
actionStatus.addMessage(messageString);
|
||||
actionUpdateStatus.getMessage().forEach(actionStatus::addMessage);
|
||||
|
||||
actionStatus.setAction(action);
|
||||
actionStatus.setOccurredAt(System.currentTimeMillis());
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class AmqpProperties {
|
||||
/**
|
||||
* DMF API dead letter queue.
|
||||
*/
|
||||
private String deadLetterQueue = "dmf_connector_deadletter";
|
||||
private String deadLetterQueue = "dmf_connector_deadletter_ttl";
|
||||
|
||||
/**
|
||||
* DMF API dead letter exchange.
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.amqp;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.when;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
|
||||
import org.eclipse.hawkbit.TestDataUtil;
|
||||
@@ -58,6 +59,12 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
@Stories("AmqpMessage Dispatcher Service Test")
|
||||
public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
private static final String TENANT = "default";
|
||||
|
||||
private static final URI AMQP_URI = IpUtil.createAmqpUri("vHost", "mytest");
|
||||
|
||||
private static final String TEST_TOKEN = "testToken";
|
||||
|
||||
private AmqpMessageDispatcherService amqpMessageDispatcherService;
|
||||
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
@@ -89,8 +96,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
@Description("Verfies that download and install event with no software modul works")
|
||||
public void testSendDownloadRequesWithEmptySoftwareModules() {
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, new ArrayList<SoftwareModule>(),
|
||||
IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
1L, TENANT, CONTROLLER_ID, 1L, new ArrayList<SoftwareModule>(), AMQP_URI, TEST_TOKEN);
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
@@ -104,7 +110,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||
distributionSetManagement);
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
1L, TENANT, CONTROLLER_ID, 1L, dsA.getModules(), AMQP_URI, TEST_TOKEN);
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
@@ -143,7 +149,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList);
|
||||
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
1L, TENANT, CONTROLLER_ID, 1L, dsA.getModules(), AMQP_URI, TEST_TOKEN);
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
@@ -154,7 +160,19 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
if (!softwareModule.getModuleId().equals(module.getId())) {
|
||||
continue;
|
||||
}
|
||||
assertFalse("The software module artifacts should not be empty", softwareModule.getArtifacts().isEmpty());
|
||||
assertThat(softwareModule.getArtifacts().size()).isEqualTo(module.getArtifacts().size()).isGreaterThan(0);
|
||||
|
||||
module.getArtifacts().forEach(dbArtifact -> {
|
||||
final Optional<org.eclipse.hawkbit.dmf.json.model.Artifact> found = softwareModule.getArtifacts()
|
||||
.stream().filter(dmfartifact -> dmfartifact.getFilename()
|
||||
.equals(((LocalArtifact) dbArtifact).getFilename()))
|
||||
.findFirst();
|
||||
|
||||
assertTrue("The artifact should exist in message", found.isPresent());
|
||||
assertThat(found.get().getSize()).isEqualTo(dbArtifact.getSize());
|
||||
assertThat(found.get().getHashes().getMd5()).isEqualTo(dbArtifact.getMd5Hash());
|
||||
assertThat(found.get().getHashes().getSha1()).isEqualTo(dbArtifact.getSha1Hash());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +180,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
@Description("Verfies that send cancel event works")
|
||||
public void testSendCancelRequest() {
|
||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
1L, TENANT, CONTROLLER_ID, 1L, AMQP_URI);
|
||||
amqpMessageDispatcherService
|
||||
.targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(cancelTargetAssignmentDistributionSetEvent.getTargetAdress());
|
||||
@@ -187,13 +205,12 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
downloadAndUpdateRequest.getActionId(), Long.valueOf(1));
|
||||
assertEquals("The topic of the event shuold contain DOWNLOAD_AND_INSTALL", EventTopic.DOWNLOAD_AND_INSTALL,
|
||||
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
|
||||
assertEquals("Security token of target", downloadAndUpdateRequest.getTargetSecurityToken(), TEST_TOKEN);
|
||||
|
||||
return downloadAndUpdateRequest;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param sendMessage
|
||||
*/
|
||||
private void assertEventMessage(final Message sendMessage) {
|
||||
assertNotNull("The message should not be null", sendMessage);
|
||||
|
||||
|
||||
@@ -333,20 +333,22 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong")
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(downloadResponse.getArtifact().getSize()).as("Wrong artifact size in message body").isEqualTo(1L);
|
||||
assertThat(downloadResponse.getArtifact().getHashes().getSha1()).as("Wrong sha1 hash").isEqualTo("sha1");
|
||||
assertThat(downloadResponse.getArtifact().getHashes().getMd5()).as("Wrong md5 hash").isEqualTo("md5");
|
||||
assertThat(downloadResponse.getDownloadUrl()).as("download url is wrong")
|
||||
.startsWith("http://localhost/api/v1/downloadserver/downloadId/");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests TODO")
|
||||
public void lookupNextUpdateActionAfterFinished() throws IllegalArgumentException, IllegalAccessException {
|
||||
public void lookupNextUpdateActionAfterFinished() throws IllegalAccessException {
|
||||
|
||||
// Mock
|
||||
final Action action = createActionWithTarget(22L, Status.FINISHED);
|
||||
when(controllerManagementMock.findActionWithDetails(Matchers.any())).thenReturn(action);
|
||||
when(controllerManagementMock.addUpdateActionStatus(Matchers.any(), Matchers.any())).thenReturn(action);
|
||||
// for the test the same action can be used
|
||||
final List<Action> actionList = new ArrayList<Action>();
|
||||
final List<Action> actionList = new ArrayList<>();
|
||||
actionList.add(action);
|
||||
when(controllerManagementMock.findActionByTargetAndActive(Matchers.any())).thenReturn(actionList);
|
||||
|
||||
@@ -372,6 +374,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
assertThat(targetAssignDistributionSetEvent.getControllerId()).as("event has wrong controller id")
|
||||
.isEqualTo("target1");
|
||||
assertThat(targetAssignDistributionSetEvent.getTargetToken()).as("targetoken not filled correctly")
|
||||
.isEqualTo(action.getTarget().getSecurityToken());
|
||||
assertThat(targetAssignDistributionSetEvent.getActionId()).as("event has wrong action id").isEqualTo(22L);
|
||||
assertThat(targetAssignDistributionSetEvent.getSoftwareModules()).as("event has wrong sofware modules")
|
||||
.isEqualTo(softwareModuleList);
|
||||
@@ -379,7 +383,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
}
|
||||
|
||||
private ActionUpdateStatus createActionUpdateStatus(final ActionStatus status) {
|
||||
return createActionUpdateStatus(status, 2l);
|
||||
return createActionUpdateStatus(status, 2L);
|
||||
}
|
||||
|
||||
private ActionUpdateStatus createActionUpdateStatus(final ActionStatus status, final Long id) {
|
||||
@@ -404,15 +408,14 @@ public class AmqpMessageHandlerServiceTest {
|
||||
}
|
||||
|
||||
private List<SoftwareModule> createSoftwareModuleList() {
|
||||
final List<SoftwareModule> softwareModuleList = new ArrayList<SoftwareModule>();
|
||||
final List<SoftwareModule> softwareModuleList = new ArrayList<>();
|
||||
final SoftwareModule softwareModule = new SoftwareModule();
|
||||
softwareModule.setId(777L);
|
||||
softwareModuleList.add(softwareModule);
|
||||
return softwareModuleList;
|
||||
}
|
||||
|
||||
private Action createActionWithTarget(final Long targetId, final Status status)
|
||||
throws IllegalArgumentException, IllegalAccessException {
|
||||
private Action createActionWithTarget(final Long targetId, final Status status) throws IllegalAccessException {
|
||||
// is needed for the creation of targets
|
||||
initalizeSecurityTokenGenerator();
|
||||
|
||||
@@ -427,7 +430,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
return action;
|
||||
}
|
||||
|
||||
private void initalizeSecurityTokenGenerator() throws IllegalArgumentException, IllegalAccessException {
|
||||
private void initalizeSecurityTokenGenerator() throws IllegalAccessException {
|
||||
final SecurityTokenGeneratorHolder instance = SecurityTokenGeneratorHolder.getInstance();
|
||||
final Field[] fields = instance.getClass().getDeclaredFields();
|
||||
for (final Field field : fields) {
|
||||
|
||||
@@ -52,6 +52,8 @@ public class BaseAmqpServiceTest {
|
||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||
actionUpdateStatus.setActionId(1L);
|
||||
actionUpdateStatus.setSoftwareModuleId(2L);
|
||||
actionUpdateStatus.getMessage().add("Message 1");
|
||||
actionUpdateStatus.getMessage().add("Message 2");
|
||||
|
||||
final Message message = rabbitTemplate.getMessageConverter().toMessage(actionUpdateStatus,
|
||||
new MessageProperties());
|
||||
|
||||
@@ -13,10 +13,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* JSON representation of artifact hash.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ArtifactHash {
|
||||
|
||||
|
||||
@@ -19,15 +19,16 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
/**
|
||||
* JSON representation of download and update request.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DownloadAndUpdateRequest {
|
||||
@JsonProperty
|
||||
private Long actionId;
|
||||
|
||||
@JsonProperty
|
||||
private String targetSecurityToken;
|
||||
|
||||
@JsonProperty
|
||||
private final List<SoftwareModule> softwareModules = new LinkedList<>();
|
||||
|
||||
@@ -39,6 +40,14 @@ public class DownloadAndUpdateRequest {
|
||||
this.actionId = correlator;
|
||||
}
|
||||
|
||||
public String getTargetSecurityToken() {
|
||||
return targetSecurityToken;
|
||||
}
|
||||
|
||||
public void setTargetSecurityToken(final String targetSecurityToken) {
|
||||
this.targetSecurityToken = targetSecurityToken;
|
||||
}
|
||||
|
||||
public List<SoftwareModule> getSoftwareModules() {
|
||||
return softwareModules;
|
||||
}
|
||||
|
||||
@@ -26,8 +26,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
public class TenantSecurityToken {
|
||||
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
public static final String COAP_AUTHORIZATION_HEADER = "Coap-Authorization";
|
||||
public static final String COAP_TOKEN_VALUE = "CoapToken";
|
||||
|
||||
@JsonProperty
|
||||
private final String tenant;
|
||||
|
||||
34
hawkbit-mgmt-ui/README.md
Normal file
34
hawkbit-mgmt-ui/README.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# hawkBit User Interface
|
||||
|
||||
The hawkBit user interface is based on the Vaadin and Vaadin-Spring framework and allows to manage software updates and large scale roll-outs via a user interface.
|
||||
|
||||
## Debugging client-side code
|
||||
### Debug using SuperDevMode
|
||||
The SuperDevMode can be used to debug client side code without any browser plugin.
|
||||
|
||||
#### Using SuperDevMode with chrome :
|
||||
|
||||
- Add required maven dependencies
|
||||
- Add vaadin-client-compiler dependency
|
||||
- Add jetty dependencies (version : 8.1x)
|
||||
- Set redirect property in the AppWidgetSet.gwt.xml module descriptor as follows
|
||||
- < set-configuration-property name="devModeRedirectEnabled" value="true" />
|
||||
- Create launch configuration for the SuperDevMode
|
||||
- The main class to execute should be com.google.gwt.dev.codeserver.CodeServer.
|
||||
- Add fully-qualified class name of widgetset (org.eclipse.hawkbit.ui.AppWidgetSet) as parameter
|
||||
- Enable debug in chrome
|
||||
- Chrome inspector window ▸ Click on settings icon ▸ Scripts ▸ Enable source maps option
|
||||
- Run the SuperDevMode Code Server with the launch configuration created above
|
||||
- Open http://localhost:8080/UI/?debug .Click on "SuperDev" button in debug console (Alternatively can directly add ?superdevmode parameter to URL)
|
||||
- Widgetset is compiled and you can see the java code files loaded in 'Chrome inspector window ▸ Source tab'
|
||||
|
||||
|
||||
#### Using SuperDevMode with Eclipse :
|
||||
|
||||
- Install the plugin from http://sdbg.github.io/p2
|
||||
- Start the server and Super Dev Mode as mentioned above
|
||||
- Create a new launch configuration in Eclipse
|
||||
- Type is "Launch Chrome"
|
||||
- http://localhost:8080/UI/?superdevmode
|
||||
- Launch the new configuration in debug mode
|
||||
- Now breakpoints in eclipse can be set
|
||||
@@ -17,7 +17,7 @@
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-mgmt-ui</artifactId>
|
||||
<name>hawkBit :: Mgmt UI</name>
|
||||
<name>hawkBit :: UI</name>
|
||||
<description>Bosch IoT Software Provisioning server web application</description>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetTagCreatedBulkEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetTagDeletedEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetTagUpdateEvent;
|
||||
|
||||
/**
|
||||
* The default hawkbit event provider.
|
||||
@@ -39,6 +40,7 @@ public class HawkbitEventProvider implements UIEventProvider {
|
||||
SINGLE_EVENTS.add(DistributionSetTagUpdateEvent.class);
|
||||
SINGLE_EVENTS.add(RolloutGroupChangeEvent.class);
|
||||
SINGLE_EVENTS.add(RolloutChangeEvent.class);
|
||||
SINGLE_EVENTS.add(TargetTagUpdateEvent.class);
|
||||
|
||||
BULK_EVENTS.add(TargetCreatedEvent.class);
|
||||
BULK_EVENTS.add(TargetInfoUpdateEvent.class);
|
||||
|
||||
@@ -37,6 +37,8 @@ public class UiProperties {
|
||||
/**
|
||||
* Demo user password.
|
||||
*/
|
||||
// Exception squid:S2068 - Empty password
|
||||
@SuppressWarnings({ "squid:S2068" })
|
||||
private String password = "";
|
||||
|
||||
public String getPassword() {
|
||||
@@ -64,6 +66,7 @@ public class UiProperties {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Links to potentially other systems (e.g. support, user management,
|
||||
* documentation etc.).
|
||||
@@ -227,6 +230,7 @@ public class UiProperties {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration of login view.
|
||||
*
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
@@ -101,8 +102,8 @@ public class BaseSwModuleBeanQuery extends AbstractBeanQuery<ProxyBaseSoftwareMo
|
||||
proxy.setVersion(bean.getVersion());
|
||||
proxy.setVendor(bean.getVendor());
|
||||
proxy.setDescription(bean.getDescription());
|
||||
proxy.setCreatedByUser(HawkbitCommonUtil.getIMUser(bean.getCreatedBy()));
|
||||
proxy.setModifiedByUser(HawkbitCommonUtil.getIMUser(bean.getLastModifiedBy()));
|
||||
proxy.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(bean));
|
||||
proxy.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(bean));
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
||||
@@ -234,12 +234,13 @@ public class SoftwareModuleAddUpdateWindow implements Serializable {
|
||||
mainLayout.addComponent(hLayout);
|
||||
mainLayout.setComponentAlignment(hLayout, Alignment.MIDDLE_LEFT);
|
||||
mainLayout.addComponents(nameTextField, versionTextField, vendorTextField, descTextArea, buttonsLayout);
|
||||
|
||||
|
||||
/* add main layout to the window */
|
||||
window = SPUIComponentProvider.getWindow(i18n.get("upload.caption.add.new.swmodule"), null,
|
||||
SPUIDefinitions.CREATE_UPDATE_WINDOW);
|
||||
window.setContent(mainLayout);
|
||||
window.setModal(true);
|
||||
nameTextField.focus();
|
||||
}
|
||||
|
||||
private void addDescriptionTextChangeListener() {
|
||||
|
||||
@@ -257,6 +257,7 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
|
||||
mainLayout = new HorizontalLayout();
|
||||
mainLayout.addComponent(fieldButtonLayout);
|
||||
setCompositionRoot(mainLayout);
|
||||
typeName.focus();
|
||||
}
|
||||
|
||||
private void addListeners() {
|
||||
@@ -553,7 +554,7 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
|
||||
.findSoftwareModuleTypeByName(typeName.getValue());
|
||||
if (createOptiongroup.getValue().equals(createTypeStr)) {
|
||||
if (!checkIsKeyDuplicate(typeKey.getValue()) && !checkIsDuplicate(existingType)) {
|
||||
crateNewSWModuleType();
|
||||
createNewSWModuleType();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -610,9 +611,9 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
|
||||
/**
|
||||
* Create new tag.
|
||||
*/
|
||||
private void crateNewSWModuleType() {
|
||||
private void createNewSWModuleType() {
|
||||
int assignNumber = 0;
|
||||
final String colorPicked = getColorPickedSting();
|
||||
final String colorPicked = getColorPickedString();
|
||||
final String typeNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeName.getValue());
|
||||
final String typeKeyValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeKey.getValue());
|
||||
final String typeDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(typeDesc.getValue());
|
||||
@@ -649,7 +650,7 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
|
||||
*
|
||||
* @return String of color picked value.
|
||||
*/
|
||||
private String getColorPickedSting() {
|
||||
private String getColorPickedString() {
|
||||
return "rgb(" + getSelPreview().getColor().getRed() + "," + getSelPreview().getColor().getGreen() + ","
|
||||
+ getSelPreview().getColor().getBlue() + ")";
|
||||
}
|
||||
@@ -675,7 +676,7 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
|
||||
|
||||
existingType.setDescription(null != typeDescValue ? typeDescValue : null);
|
||||
|
||||
existingType.setColour(getColorPickedSting());
|
||||
existingType.setColour(getColorPickedString());
|
||||
swTypeManagementService.updateSoftwareModuleType(existingType);
|
||||
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { existingType.getName() }));
|
||||
closeWindow();
|
||||
|
||||
@@ -37,20 +37,12 @@ import com.vaadin.ui.Upload.SucceededListener;
|
||||
* {@link StreamVariable} upload variants.
|
||||
*
|
||||
* The handler manages the output to the user and at the same time ensures that
|
||||
* the upload does not exceed the configued max file size.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* the upload does not exceed the configured max file size.
|
||||
*
|
||||
*/
|
||||
public class UploadHandler implements StreamVariable, Receiver, SucceededListener, FailedListener, FinishedListener,
|
||||
ProgressListener, StartedListener {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UploadHandler.class);
|
||||
@@ -108,7 +100,7 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
public OutputStream receiveUpload(final String fileName, final String mimeType) {
|
||||
this.fileName = fileName;
|
||||
this.mimeType = mimeType;
|
||||
//reset has directory flag before upload
|
||||
// reset has directory flag before upload
|
||||
view.setHasDirectory(false);
|
||||
try {
|
||||
if (view.checkIfSoftwareModuleIsSelected()) {
|
||||
@@ -343,11 +335,6 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
@@ -356,11 +343,6 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* 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.common;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.hawkbit.im.authentication.UserPrincipal;
|
||||
import org.eclipse.hawkbit.repository.model.BaseEntity;
|
||||
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
|
||||
import com.vaadin.server.VaadinService;
|
||||
|
||||
/**
|
||||
* A Utility class to user details e.g. username
|
||||
*/
|
||||
public final class UserDetailsFormatter {
|
||||
|
||||
private static final String TRIM_APPENDIX = "...";
|
||||
private static final String DETAIL_SEPERATOR = ", ";
|
||||
|
||||
private UserDetailsFormatter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load user details by the user name and format the user name to max 100
|
||||
* characters.
|
||||
*
|
||||
* @see {@link UserDetailsFormatter#loadAndFormatUsername(String, int)}
|
||||
*
|
||||
* @param username
|
||||
* the user name
|
||||
* @return the formatted user name (max 100 characters) cannot be <null>
|
||||
*/
|
||||
public static String loadAndFormatUsername(final String username) {
|
||||
return loadAndFormatUsername(username, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load user details by {@link BaseEntity#getCreatedBy()} and format the
|
||||
* user name. Use {@link UserDetailsFormatter#loadAndFormatUsername(String)}
|
||||
*
|
||||
* @param baseEntity
|
||||
* the entity
|
||||
* @return the formatted 'created at user name' (max 100 characters) cannot
|
||||
* be <null>
|
||||
*/
|
||||
public static String loadAndFormatCreatedBy(final BaseEntity baseEntity) {
|
||||
if (baseEntity == null || baseEntity.getCreatedBy() == null) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
return loadAndFormatUsername(baseEntity.getCreatedBy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load user details by {@link BaseEntity#getLastModifiedBy()} and format
|
||||
* the user name. Use
|
||||
* {@link UserDetailsFormatter#loadAndFormatUsername(String)}
|
||||
*
|
||||
* @param baseEntity
|
||||
* the entity
|
||||
* @return the formatted 'last modefied by user name' (max 100 characters)
|
||||
* cannot be <null>
|
||||
*/
|
||||
public static String loadAndFormatLastModifiedBy(final BaseEntity baseEntity) {
|
||||
if (baseEntity == null || baseEntity.getLastModifiedBy() == null) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
return loadAndFormatUsername(baseEntity.getLastModifiedBy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Load user details by the current session information and format the user
|
||||
* name to max 12 characters. @see
|
||||
* {@link UserDetailsFormatter#loadAndFormatUsername(String, int)}
|
||||
*
|
||||
* @return the formatted user name (max 12 characters) cannot be <null>
|
||||
*/
|
||||
public static String formatCurrentUsername() {
|
||||
return loadAndFormatUsername(getCurrentUser().getUsername(), 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load user details by the user name and format the user name. If the
|
||||
* loaded {@link UserDetails} is not an instance of a {@link UserPrincipal},
|
||||
* then just the {@link UserDetails#getUsername()} will return.
|
||||
*
|
||||
* If first and last name available, they will combined. Otherwise the
|
||||
* {@link UserPrincipal#getLoginname()} will formatted. The formatted name
|
||||
* is reduced to 100 characters.
|
||||
*
|
||||
* @param username
|
||||
* the user name
|
||||
* @param expectedNameLength
|
||||
* the name size of each name part
|
||||
* @return the formatted user name (max expectedNameLength characters)
|
||||
* cannot be <null>
|
||||
*/
|
||||
public static String loadAndFormatUsername(final String username, final int expectedNameLength) {
|
||||
final UserDetails userDetails = loadUserByUsername(username);
|
||||
return formatUserName(expectedNameLength, userDetails);
|
||||
}
|
||||
|
||||
private static String formatUserName(final int expectedNameLength, final UserDetails userDetails) {
|
||||
if (!(userDetails instanceof UserPrincipal)) {
|
||||
return userDetails.getUsername();
|
||||
}
|
||||
|
||||
final UserPrincipal userPrincipal = (UserPrincipal) userDetails;
|
||||
|
||||
String firstname = StringUtils.defaultIfEmpty(userPrincipal.getFirstname(), StringUtils.EMPTY);
|
||||
|
||||
if (!StringUtils.isEmpty(firstname)) {
|
||||
firstname += DETAIL_SEPERATOR;
|
||||
}
|
||||
|
||||
final String firstAndLastname = firstname
|
||||
+ StringUtils.defaultIfEmpty(userPrincipal.getLastname(), StringUtils.EMPTY);
|
||||
|
||||
final String trimmedUsername = trimAndFormatDetail(firstAndLastname, expectedNameLength);
|
||||
|
||||
if (StringUtils.isEmpty(trimmedUsername)) {
|
||||
return trimAndFormatDetail(userPrincipal.getLoginname(), expectedNameLength);
|
||||
}
|
||||
return trimmedUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the current tenant. The information is loaded by the current
|
||||
* session information.
|
||||
*
|
||||
* @return the formatted user name (max 8 characters) can be <null>
|
||||
*/
|
||||
public static String formatCurrentTenant() {
|
||||
final UserDetails userDetails = getCurrentUser();
|
||||
if (!(userDetails instanceof UserPrincipal)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final UserPrincipal userPrincipal = (UserPrincipal) userDetails;
|
||||
return trimAndFormatDetail(userPrincipal.getTenant(), 8);
|
||||
}
|
||||
|
||||
private static UserDetails getCurrentUser() {
|
||||
final SecurityContext context = (SecurityContext) VaadinService.getCurrentRequest().getWrappedSession()
|
||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
return (UserDetails) context.getAuthentication().getPrincipal();
|
||||
}
|
||||
|
||||
private static String trimAndFormatDetail(final String formatString, final int expectedDetailLength) {
|
||||
final String detail = StringUtils.defaultIfEmpty(formatString, StringUtils.EMPTY);
|
||||
final String trimmedDetail = StringUtils.substring(detail, 0, expectedDetailLength);
|
||||
if (StringUtils.length(detail) > expectedDetailLength) {
|
||||
return trimmedDetail + TRIM_APPENDIX;
|
||||
}
|
||||
return trimmedDetail;
|
||||
}
|
||||
|
||||
// Exception squid:S1166 - exception has to be hidden
|
||||
@SuppressWarnings({ "squid:S1166" })
|
||||
private static UserDetails loadUserByUsername(final String username) {
|
||||
final UserDetailsService userDetailsService = SpringContextHelper.getBean(UserDetailsService.class);
|
||||
try {
|
||||
final UserDetails loadUserByUsername = userDetailsService.loadUserByUsername(username);
|
||||
if (loadUserByUsername == null) {
|
||||
throw new UsernameNotFoundException("User not found " + username);
|
||||
}
|
||||
return loadUserByUsername;
|
||||
} catch (final UsernameNotFoundException e) {
|
||||
return new User(username, "", Collections.emptyList());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,20 +150,20 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
||||
|
||||
private void buildLayout() {
|
||||
final HorizontalLayout nameEditLayout = new HorizontalLayout();
|
||||
nameEditLayout.setWidth(100.0f, Unit.PERCENTAGE);
|
||||
nameEditLayout.setWidth(100.0F, Unit.PERCENTAGE);
|
||||
nameEditLayout.addComponent(caption);
|
||||
nameEditLayout.setComponentAlignment(caption, Alignment.MIDDLE_LEFT);
|
||||
nameEditLayout.setComponentAlignment(caption, Alignment.TOP_LEFT);
|
||||
if (hasEditPermission()) {
|
||||
nameEditLayout.addComponent(editButton);
|
||||
nameEditLayout.setComponentAlignment(editButton, Alignment.MIDDLE_RIGHT);
|
||||
nameEditLayout.setComponentAlignment(editButton, Alignment.TOP_RIGHT);
|
||||
}
|
||||
nameEditLayout.setExpandRatio(caption, 1.0f);
|
||||
nameEditLayout.setExpandRatio(caption, 1.0F);
|
||||
nameEditLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
||||
|
||||
addComponent(nameEditLayout);
|
||||
setComponentAlignment(nameEditLayout, Alignment.MIDDLE_CENTER);
|
||||
setComponentAlignment(nameEditLayout, Alignment.TOP_CENTER);
|
||||
addComponent(detailsTab);
|
||||
setComponentAlignment(nameEditLayout, Alignment.MIDDLE_CENTER);
|
||||
setComponentAlignment(nameEditLayout, Alignment.TOP_CENTER);
|
||||
|
||||
setSizeFull();
|
||||
setHeightUndefined();
|
||||
@@ -171,9 +171,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
||||
}
|
||||
|
||||
private Label createHeaderCaption() {
|
||||
final Label captionLabel = SPUIComponentProvider.getLabel(getDefaultCaption(),
|
||||
SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
return captionLabel;
|
||||
return SPUIComponentProvider.getLabel(getDefaultCaption(), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
}
|
||||
|
||||
protected VerticalLayout getTabLayout() {
|
||||
@@ -213,22 +211,22 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
||||
populateDetailsWidget();
|
||||
}
|
||||
|
||||
protected void updateLogLayout(final VerticalLayout changeLogLayout, final Long lastModifiedAt,
|
||||
final String lastModifiedBy, final Long createdAt, final String createdBy, final I18N i18n) {
|
||||
changeLogLayout.removeAllComponents();
|
||||
changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.created.at"),
|
||||
createdAt == null ? "" : SPDateTimeUtil.getFormattedDate(createdAt)));
|
||||
protected void populateLog() {
|
||||
logLayout.removeAllComponents();
|
||||
|
||||
changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.created.by"),
|
||||
createdBy == null ? "" : HawkbitCommonUtil.getIMUser(createdBy)));
|
||||
logLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.created.at"),
|
||||
SPDateTimeUtil.formatCreatedAt(selectedBaseEntity)));
|
||||
|
||||
if (null != lastModifiedAt) {
|
||||
changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.modified.date"),
|
||||
SPDateTimeUtil.getFormattedDate(lastModifiedAt)));
|
||||
logLayout.addComponent(SPUIComponentProvider.createCreatedByLabel(i18n, selectedBaseEntity));
|
||||
|
||||
changeLogLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.modified.by"),
|
||||
lastModifiedBy == null ? "" : HawkbitCommonUtil.getIMUser(lastModifiedBy)));
|
||||
if (selectedBaseEntity == null || selectedBaseEntity.getLastModifiedAt() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
logLayout.addComponent(SPUIComponentProvider.createNameValueLabel(i18n.get("label.modified.date"),
|
||||
SPDateTimeUtil.formatLastModifiedAt(selectedBaseEntity)));
|
||||
|
||||
logLayout.addComponent(SPUIComponentProvider.createLastModifiedByLabel(i18n, selectedBaseEntity));
|
||||
}
|
||||
|
||||
protected void updateDescriptionLayout(final String descriptionLabel, final String description) {
|
||||
@@ -320,19 +318,6 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
||||
return detailsLayout;
|
||||
}
|
||||
|
||||
public VerticalLayout getLogLayout() {
|
||||
return logLayout;
|
||||
}
|
||||
|
||||
private void populateLog() {
|
||||
if (selectedBaseEntity == null) {
|
||||
updateLogLayout(getLogLayout(), null, StringUtils.EMPTY, null, null, i18n);
|
||||
return;
|
||||
}
|
||||
updateLogLayout(getLogLayout(), selectedBaseEntity.getLastModifiedAt(), selectedBaseEntity.getLastModifiedBy(),
|
||||
selectedBaseEntity.getCreatedAt(), selectedBaseEntity.getCreatedBy(), i18n);
|
||||
}
|
||||
|
||||
private void populateDescription() {
|
||||
if (selectedBaseEntity != null) {
|
||||
updateDescriptionLayout(i18n.get("label.description"), selectedBaseEntity.getDescription());
|
||||
|
||||
@@ -20,7 +20,7 @@ import javax.annotation.PreDestroy;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
|
||||
import org.eclipse.hawkbit.ui.common.ManagmentEntityState;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
@@ -212,9 +212,9 @@ public abstract class AbstractTable<E extends NamedEntity, I> extends Table {
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_ID).setValue(baseEntity.getId());
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_DESC).setValue(baseEntity.getDescription());
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_CREATED_BY)
|
||||
.setValue(HawkbitCommonUtil.getIMUser(baseEntity.getCreatedBy()));
|
||||
.setValue(UserDetailsFormatter.loadAndFormatCreatedBy(baseEntity));
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY)
|
||||
.setValue(HawkbitCommonUtil.getIMUser(baseEntity.getLastModifiedBy()));
|
||||
.setValue(UserDetailsFormatter.loadAndFormatLastModifiedBy(baseEntity));
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_CREATED_DATE)
|
||||
.setValue(SPDateTimeUtil.getFormattedDate(baseEntity.getCreatedAt()));
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE)
|
||||
@@ -329,6 +329,17 @@ public abstract class AbstractTable<E extends NamedEntity, I> extends Table {
|
||||
columnList.add(
|
||||
new TableColumn(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, i18n.get("header.modifiedDate"), 0.1F));
|
||||
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_DESC, i18n.get("header.description"), 0.2F));
|
||||
setItemDescriptionGenerator((source, itemId, propertyId) -> {
|
||||
|
||||
if (SPUILabelDefinitions.VAR_CREATED_BY.equals(propertyId)) {
|
||||
return getItem(itemId).getItemProperty(SPUILabelDefinitions.VAR_CREATED_BY).getValue().toString();
|
||||
}
|
||||
if (SPUILabelDefinitions.VAR_LAST_MODIFIED_BY.equals(propertyId)) {
|
||||
return getItem(itemId).getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY).getValue().toString();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
return columnList;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ import com.vaadin.ui.VerticalLayout;
|
||||
public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
|
||||
private static final long serialVersionUID = 4881626370291837175L;
|
||||
|
||||
|
||||
@Autowired
|
||||
protected I18N i18n;
|
||||
|
||||
@@ -53,7 +53,6 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
|
||||
@Autowired
|
||||
protected transient EventBus.SessionEventBus eventbus;
|
||||
|
||||
|
||||
private Label headerCaption;
|
||||
|
||||
@@ -83,7 +82,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
restoreState();
|
||||
eventbus.subscribe(this);
|
||||
}
|
||||
|
||||
|
||||
@PreDestroy
|
||||
void destroy() {
|
||||
eventbus.unsubscribe(this);
|
||||
@@ -171,8 +170,8 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
}
|
||||
titleFilterIconsLayout.addComponent(maxMinIcon);
|
||||
titleFilterIconsLayout.setComponentAlignment(maxMinIcon, Alignment.TOP_RIGHT);
|
||||
titleFilterIconsLayout.setExpandRatio(headerCaption, 0.4f);
|
||||
titleFilterIconsLayout.setExpandRatio(searchField, 0.6f);
|
||||
titleFilterIconsLayout.setExpandRatio(headerCaption, 0.4F);
|
||||
titleFilterIconsLayout.setExpandRatio(searchField, 0.6F);
|
||||
|
||||
addComponent(titleFilterIconsLayout);
|
||||
|
||||
@@ -192,10 +191,10 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
||||
|
||||
dropHintDropFilterLayout.addComponent(dropFilterLayout);
|
||||
dropHintDropFilterLayout.setComponentAlignment(dropFilterLayout, Alignment.TOP_CENTER);
|
||||
dropHintDropFilterLayout.setExpandRatio(dropFilterLayout, 1.0f);
|
||||
dropHintDropFilterLayout.setExpandRatio(dropFilterLayout, 1.0F);
|
||||
}
|
||||
addComponent(dropHintDropFilterLayout);
|
||||
setComponentAlignment(dropHintDropFilterLayout, Alignment.MIDDLE_CENTER);
|
||||
setComponentAlignment(dropHintDropFilterLayout, Alignment.TOP_CENTER);
|
||||
addStyleName("bordered-layout");
|
||||
addStyleName("no-border-bottom");
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ public class ProxyTarget extends Target {
|
||||
|
||||
private DistributionSet installedDistributionSet;
|
||||
|
||||
private DistributionSet assignedDistributionSet;
|
||||
|
||||
private TargetIdName targetIdName;
|
||||
|
||||
private String assignedDistNameVersion;
|
||||
@@ -249,6 +251,21 @@ public class ProxyTarget extends Target {
|
||||
this.installedDistributionSet = installedDistributionSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the assignedDistributionSet
|
||||
*/
|
||||
public DistributionSet getAssignedDistributionSet() {
|
||||
return assignedDistributionSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param assignedDistributionSet
|
||||
* the assignedDistributionSet to set
|
||||
*/
|
||||
public void setAssignedDistributionSet(DistributionSet assignedDistributionSet) {
|
||||
this.assignedDistributionSet = assignedDistributionSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the targetIdName
|
||||
*/
|
||||
@@ -297,4 +314,5 @@ public class ProxyTarget extends Target {
|
||||
public void setStatus(final Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.hawkbit.repository.model.BaseEntity;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIHeaderLayoutDecorator;
|
||||
@@ -20,6 +22,7 @@ import org.eclipse.hawkbit.ui.decorators.SPUILabelDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUITextAreaDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUITextFieldDecorator;
|
||||
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -328,6 +331,50 @@ public final class SPUIComponentProvider {
|
||||
return nameValueLabel;
|
||||
}
|
||||
|
||||
private static Label createUsernameLabel(final String label, final String username) {
|
||||
String loadAndFormatUsername = StringUtils.EMPTY;
|
||||
if (!StringUtils.isEmpty(username)) {
|
||||
loadAndFormatUsername = UserDetailsFormatter.loadAndFormatUsername(username);
|
||||
}
|
||||
|
||||
final Label nameValueLabel = new Label(getBoldHTMLText(label) + loadAndFormatUsername, ContentMode.HTML);
|
||||
nameValueLabel.setSizeFull();
|
||||
nameValueLabel.addStyleName(SPUIDefinitions.TEXT_STYLE);
|
||||
nameValueLabel.addStyleName("label-style");
|
||||
nameValueLabel.setDescription(loadAndFormatUsername);
|
||||
return nameValueLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create label which represents the {@link BaseEntity#getCreatedBy()} by
|
||||
* user name
|
||||
*
|
||||
* @param i18n
|
||||
* the i18n
|
||||
* @param baseEntity
|
||||
* the entity
|
||||
* @return the label
|
||||
*/
|
||||
public static Label createCreatedByLabel(final I18N i18n, final BaseEntity baseEntity) {
|
||||
return createUsernameLabel(i18n.get("label.created.by"),
|
||||
baseEntity == null ? StringUtils.EMPTY : baseEntity.getCreatedBy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create label which represents the
|
||||
* {@link BaseEntity#getLastModifiedBy()()} by user name
|
||||
*
|
||||
* @param i18n
|
||||
* the i18n
|
||||
* @param baseEntity
|
||||
* the entity
|
||||
* @return the label
|
||||
*/
|
||||
public static Label createLastModifiedByLabel(final I18N i18n, final BaseEntity baseEntity) {
|
||||
return createUsernameLabel(i18n.get("label.modified.by"),
|
||||
baseEntity == null ? StringUtils.EMPTY : baseEntity.getLastModifiedBy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bold Text.
|
||||
*
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* 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.customrenderers.client;
|
||||
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer;
|
||||
|
||||
import com.vaadin.client.connectors.ButtonRendererConnector;
|
||||
import com.vaadin.shared.ui.Connect;
|
||||
|
||||
/**
|
||||
*
|
||||
* A connector for {@link LinkRenderer}.
|
||||
*
|
||||
*/
|
||||
@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer.class)
|
||||
public class LinkRendererConnector extends ButtonRendererConnector {
|
||||
private static final long serialVersionUID = 7987417436367399331L;
|
||||
|
||||
@Override
|
||||
public org.eclipse.hawkbit.ui.customrenderers.client.renderers.LinkRenderer getRenderer() {
|
||||
return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.LinkRenderer) super.getRenderer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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.customrenderers.client;
|
||||
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
|
||||
import com.google.web.bindery.event.shared.HandlerRegistration;
|
||||
import com.vaadin.client.connectors.ClickableRendererConnector;
|
||||
import com.vaadin.client.renderers.ClickableRenderer.RendererClickHandler;
|
||||
import com.vaadin.shared.ui.Connect;
|
||||
|
||||
import elemental.json.JsonObject;
|
||||
/**
|
||||
* A connector for {@link CustomObjectRenderer }.
|
||||
*
|
||||
*/
|
||||
@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer.class)
|
||||
public class RolloutRendererConnector extends ClickableRendererConnector<RolloutRendererData> {
|
||||
private static final long serialVersionUID = 7734682321931830566L;
|
||||
|
||||
public org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer getRenderer() {
|
||||
return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer) super.getRenderer();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HandlerRegistration addClickHandler(
|
||||
RendererClickHandler<JsonObject> handler) {
|
||||
return getRenderer().addClickHandler(handler);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* 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.customrenderers.client.renderers;
|
||||
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.vaadin.client.renderers.ButtonRenderer;
|
||||
import com.vaadin.client.ui.VButton;
|
||||
import com.vaadin.client.widget.grid.RendererCellReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* Renders link with provided text.
|
||||
*
|
||||
*/
|
||||
public class LinkRenderer extends ButtonRenderer {
|
||||
@Override
|
||||
public void render(RendererCellReference cell, String text, Button button) {
|
||||
button.setText(text);
|
||||
applystyle(button);
|
||||
// this is to allow the button to disappear, if the text is null
|
||||
button.setVisible(text != null);
|
||||
button.getElement().setId(new StringBuilder("link").append(".").append(text).toString());
|
||||
}
|
||||
|
||||
private void applystyle(Button button) {
|
||||
button.setStyleName(VButton.CLASSNAME);
|
||||
button.addStyleName(getStyle("borderless"));
|
||||
button.addStyleName(getStyle("small"));
|
||||
button.addStyleName(getStyle("on-focus-no-border"));
|
||||
button.addStyleName(getStyle("link"));
|
||||
}
|
||||
|
||||
private String getStyle(final String style) {
|
||||
return new StringBuilder(style).append(" ").append(VButton.CLASSNAME).append("-").append(style).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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.customrenderers.client.renderers;
|
||||
|
||||
import com.google.gwt.core.shared.GWT;
|
||||
import com.vaadin.client.renderers.ClickableRenderer;
|
||||
import com.vaadin.client.ui.VButton;
|
||||
import com.vaadin.client.widget.grid.RendererCellReference;
|
||||
|
||||
/**
|
||||
* Renders button with provided CustomObject.
|
||||
* Used to display button with link.
|
||||
*
|
||||
*/
|
||||
public class RolloutRenderer extends ClickableRenderer<RolloutRendererData, VButton> {
|
||||
|
||||
@Override
|
||||
public VButton createWidget() {
|
||||
VButton b = GWT.create(VButton.class);
|
||||
b.addClickHandler(this);
|
||||
b.setStylePrimaryName("v-nativebutton");
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(RendererCellReference cell, RolloutRendererData text, VButton button) {
|
||||
final String creating = "CREATING";
|
||||
button.setText(text.getName());
|
||||
applystyle(button);
|
||||
// this is to allow the button to disappear, if the text is null
|
||||
button.setVisible(text.getName() != null);
|
||||
button.getElement().setId(new StringBuilder("link").append(".").append(text.getName()).toString());
|
||||
/*
|
||||
* checking Rollout Status for applying button style. If Rollout status
|
||||
* is not "CREATING", then the Rollout button is applying hyperlink
|
||||
* style
|
||||
*/
|
||||
final boolean isStatusCreate = text.getStatus() != null && creating.equalsIgnoreCase(text.getStatus());
|
||||
if (isStatusCreate) {
|
||||
button.addStyleName(getStyle("boldhide"));
|
||||
button.setEnabled(false);
|
||||
} else {
|
||||
button.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void applystyle(VButton button) {
|
||||
button.setStyleName(VButton.CLASSNAME);
|
||||
button.addStyleName(getStyle("borderless"));
|
||||
button.addStyleName(getStyle("small"));
|
||||
button.addStyleName(getStyle("on-focus-no-border"));
|
||||
button.addStyleName(getStyle("link"));
|
||||
}
|
||||
|
||||
private String getStyle(final String style) {
|
||||
return new StringBuilder(style).append(" ").append(VButton.CLASSNAME).append("-").append(style).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.customrenderers.client.renderers;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* RendererData class with Name and Status.
|
||||
*
|
||||
*/
|
||||
|
||||
public class RolloutRendererData implements Serializable {
|
||||
private static final long serialVersionUID = -5018181529953620263L;
|
||||
|
||||
private String name;
|
||||
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* Initialize the RendererData.
|
||||
*/
|
||||
public RolloutRendererData() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the RendererData.
|
||||
*
|
||||
* @param name
|
||||
* Name of the Rollout.
|
||||
* @param status
|
||||
* Status of Rollout.
|
||||
*/
|
||||
public RolloutRendererData(String name, String status) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/**
|
||||
* 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.customrenderers.renderers;
|
||||
|
||||
import com.vaadin.ui.renderers.ButtonRenderer;
|
||||
|
||||
/**
|
||||
*
|
||||
* Renders link with provided text.
|
||||
*
|
||||
*/
|
||||
public class LinkRenderer extends ButtonRenderer {
|
||||
private static final long serialVersionUID = -1242995370043404892L;
|
||||
|
||||
/**
|
||||
* Intialise link renderer.
|
||||
*/
|
||||
public LinkRenderer() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Intialise link renderer with {@link RendererClickListener}
|
||||
*
|
||||
* @param listener
|
||||
* RendererClickListener
|
||||
*/
|
||||
public LinkRenderer(RendererClickListener listener) {
|
||||
super(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.customrenderers.renderers;
|
||||
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
|
||||
import com.vaadin.ui.renderers.ClickableRenderer;
|
||||
|
||||
import elemental.json.JsonValue;
|
||||
|
||||
/**
|
||||
* Renders button with provided CustomObject.
|
||||
* Used to display button with link.
|
||||
*
|
||||
*/
|
||||
|
||||
public class RolloutRenderer extends ClickableRenderer<RolloutRendererData> {
|
||||
|
||||
private static final long serialVersionUID = -8754180585906263554L;
|
||||
|
||||
/**
|
||||
* Creates a new custom object renderer.
|
||||
*/
|
||||
public RolloutRenderer() {
|
||||
super(RolloutRendererData.class, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize custom object renderer with {@link Class<CustomObject>}
|
||||
*
|
||||
* @param presentationType
|
||||
* Class<CustomObject>
|
||||
*/
|
||||
|
||||
public RolloutRenderer(Class<RolloutRendererData> presentationType) {
|
||||
super(presentationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new custom object renderer and adds the given click listener to it.
|
||||
*
|
||||
* @param listener
|
||||
* the click listener to register
|
||||
*/
|
||||
public RolloutRenderer(RendererClickListener listener) {
|
||||
this();
|
||||
addClickListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonValue encode(RolloutRendererData resource) {
|
||||
return super.encode(resource, RolloutRendererData.class);
|
||||
}
|
||||
}
|
||||
@@ -284,7 +284,7 @@ public class CreateUpdateDistSetTypeLayout extends CustomComponent implements Co
|
||||
|
||||
mainLayout.addComponent(fieldLayout);
|
||||
mainLayout.addComponent(twinTableLayout);
|
||||
|
||||
|
||||
colorLayout = new HorizontalLayout();
|
||||
sliderLayout = new VerticalLayout();
|
||||
final HorizontalLayout chooseColorLayout = new HorizontalLayout();
|
||||
@@ -299,6 +299,7 @@ public class CreateUpdateDistSetTypeLayout extends CustomComponent implements Co
|
||||
mainWindowLayout.addComponent(colorLayout);
|
||||
mainWindowLayout.addComponent(buttonLayout);
|
||||
setCompositionRoot(mainWindowLayout);
|
||||
typeName.focus();
|
||||
}
|
||||
|
||||
private HorizontalLayout createTwinColumnLayout() {
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.ProxyDistribution;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
@@ -113,8 +114,8 @@ public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
||||
proxyDistribution.setCreatedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getCreatedAt()));
|
||||
proxyDistribution.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getLastModifiedAt()));
|
||||
proxyDistribution.setDescription(distributionSet.getDescription());
|
||||
proxyDistribution.setCreatedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getCreatedBy()));
|
||||
proxyDistribution.setModifiedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getLastModifiedBy()));
|
||||
proxyDistribution.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(distributionSet));
|
||||
proxyDistribution.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(distributionSet));
|
||||
proxyDistribution.setIsComplete(distributionSet.isComplete());
|
||||
proxyDistributions.add(proxyDistribution);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||
import org.eclipse.hawkbit.repository.model.CustomSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
@@ -99,8 +100,8 @@ public class SwModuleBeanQuery extends AbstractBeanQuery<ProxyBaseSwModuleItem>
|
||||
proxyItem.setVersion(bean.getVersion());
|
||||
proxyItem.setVendor(bean.getVendor());
|
||||
proxyItem.setDescription(bean.getDescription());
|
||||
proxyItem.setCreatedByUser(HawkbitCommonUtil.getIMUser(bean.getCreatedBy()));
|
||||
proxyItem.setModifiedByUser(HawkbitCommonUtil.getIMUser(bean.getLastModifiedBy()));
|
||||
proxyItem.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(bean));
|
||||
proxyItem.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(bean));
|
||||
proxyItem.setAssigned(customSoftwareModule.isAssigned());
|
||||
proxyItem.setColour(bean.getType().getColour());
|
||||
proxyItem.setTypeId(bean.getType().getId());
|
||||
|
||||
@@ -68,6 +68,8 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
|
||||
private static final long serialVersionUID = 7474232427119031474L;
|
||||
|
||||
private static final String breadcrumbCustomFilters = "breadcrumb.target.filter.custom.filters";
|
||||
|
||||
@Autowired
|
||||
private I18N i18n;
|
||||
|
||||
@@ -93,6 +95,12 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
@Qualifier("uiExecutor")
|
||||
private transient Executor executor;
|
||||
|
||||
private HorizontalLayout breadcrumbLayout;
|
||||
|
||||
private Button breadcrumbButton;
|
||||
|
||||
private Label breadcrumbName;
|
||||
|
||||
private Label headerCaption;
|
||||
|
||||
private TextField queryTextField;
|
||||
@@ -169,6 +177,7 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
oldFilterName = filterManagementUIState.getTfQuery().get().getName();
|
||||
oldFilterQuery = filterManagementUIState.getTfQuery().get().getQuery();
|
||||
}
|
||||
breadcrumbName.setValue(nameLabel.getValue());
|
||||
showValidationSuccesIcon();
|
||||
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.TARGET_FILTER_CAPTION_LAYOUT);
|
||||
headerCaption.setVisible(false);
|
||||
@@ -177,6 +186,7 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
|
||||
private void resetComponents() {
|
||||
headerCaption.setVisible(true);
|
||||
breadcrumbName.setValue(headerCaption.getValue());
|
||||
nameLabel.setValue("");
|
||||
queryTextField.setValue("");
|
||||
setInitialStatusIconStyle(validationIcon);
|
||||
@@ -201,6 +211,9 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
}
|
||||
|
||||
private void createComponents() {
|
||||
|
||||
breadcrumbButton = createBreadcrumbButton();
|
||||
|
||||
headerCaption = SPUIComponentProvider.getLabel(SPUILabelDefinitions.VAR_CREATE_FILTER,
|
||||
SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
|
||||
@@ -221,12 +234,23 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
closeIcon = createSearchResetIcon();
|
||||
}
|
||||
|
||||
private Button createBreadcrumbButton() {
|
||||
final Button createFilterViewLink = SPUIComponentProvider.getButton(null, "", "", null, false, null,
|
||||
SPUIButtonStyleSmallNoBorder.class);
|
||||
createFilterViewLink.setStyleName(ValoTheme.LINK_SMALL + " " + "on-focus-no-border link rollout-caption-links");
|
||||
createFilterViewLink.setDescription(i18n.get(breadcrumbCustomFilters));
|
||||
createFilterViewLink.setCaption(i18n.get(breadcrumbCustomFilters));
|
||||
createFilterViewLink.addClickListener(value -> showCustomFiltersView());
|
||||
|
||||
return createFilterViewLink;
|
||||
}
|
||||
|
||||
private TextField createNameTextField() {
|
||||
final TextField nameField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, null,
|
||||
i18n.get("textfield.customfiltername"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
nameField.setId(SPUIComponetIdProvider.CUSTOM_FILTER_ADD_NAME);
|
||||
nameField.setPropertyDataSource(nameLabel);
|
||||
nameField.addTextChangeListener(event -> onFiterNameChange(event));
|
||||
nameField.addTextChangeListener(event -> onFilterNameChange(event));
|
||||
return nameField;
|
||||
}
|
||||
|
||||
@@ -256,7 +280,7 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
};
|
||||
}
|
||||
|
||||
private void onFiterNameChange(final TextChangeEvent event) {
|
||||
private void onFilterNameChange(final TextChangeEvent event) {
|
||||
if (isNameAndQueryEmpty(event.getText(), queryTextField.getValue())
|
||||
|| (event.getText().equals(oldFilterName) && queryTextField.getValue().equals(oldFilterQuery))) {
|
||||
saveButton.setEnabled(false);
|
||||
@@ -276,6 +300,13 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
titleFilterIconsLayout.addComponents(headerCaption, captionLayout);
|
||||
titleFilterIconsLayout.setSpacing(true);
|
||||
|
||||
breadcrumbLayout = new HorizontalLayout();
|
||||
breadcrumbLayout.addComponent(breadcrumbButton);
|
||||
breadcrumbLayout.addComponent(new Label(">"));
|
||||
breadcrumbName = SPUIComponentProvider.getLabel(null, SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
||||
breadcrumbLayout.addComponent(breadcrumbName);
|
||||
breadcrumbName.addStyleName("breadcrumbPaddingLeft");
|
||||
|
||||
final HorizontalLayout titleFilterLayout = new HorizontalLayout();
|
||||
titleFilterLayout.setSizeFull();
|
||||
titleFilterLayout.addComponents(titleFilterIconsLayout, closeIcon);
|
||||
@@ -290,7 +321,7 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
searchLayout.setSpacing(false);
|
||||
searchLayout.addComponents(validationIcon, queryTextField);
|
||||
searchLayout.addStyleName("custom-search-layout");
|
||||
searchLayout.setComponentAlignment(validationIcon, Alignment.MIDDLE_CENTER);
|
||||
searchLayout.setComponentAlignment(validationIcon, Alignment.TOP_CENTER);
|
||||
|
||||
final HorizontalLayout iconLayout = new HorizontalLayout();
|
||||
iconLayout.setSizeUndefined();
|
||||
@@ -302,10 +333,12 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
queryLayout.setSpacing(true);
|
||||
queryLayout.addComponents(searchLayout, iconLayout);
|
||||
|
||||
addComponent(breadcrumbLayout);
|
||||
addComponent(titleFilterLayout);
|
||||
addComponent(queryLayout);
|
||||
setSpacing(true);
|
||||
addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
||||
addStyleName("bordered-layout");
|
||||
}
|
||||
|
||||
private void setUpCaptionLayout(final boolean isCreateView) {
|
||||
@@ -524,4 +557,8 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button
|
||||
}
|
||||
}
|
||||
|
||||
private void showCustomFiltersView() {
|
||||
eventBus.publish(this, CustomFilterUIEvent.SHOW_FILTER_MANAGEMENT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,10 +17,12 @@ import java.util.Map;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.event.CustomFilterUIEvent;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.state.FilterManagementUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.AssignInstalledDSTooltipGenerator;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||
@@ -69,6 +71,10 @@ public class CreateOrUpdateFilterTable extends Table {
|
||||
|
||||
private static final int PROPERTY_DEPT = 3;
|
||||
|
||||
private static final String ASSIGN_DIST_SET = "assignedDistributionSet";
|
||||
|
||||
private static final String INSTALL_DIST_SET = "installedDistributionSet";
|
||||
|
||||
/**
|
||||
* Initialize the Action History Table.
|
||||
*/
|
||||
@@ -87,6 +93,7 @@ public class CreateOrUpdateFilterTable extends Table {
|
||||
setId(SPUIComponetIdProvider.CUSTOM_FILTER_TARGET_TABLE_ID);
|
||||
setSelectable(false);
|
||||
eventBus.subscribe(this);
|
||||
setItemDescriptionGenerator(new AssignInstalledDSTooltipGenerator());
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@@ -160,6 +167,9 @@ public class CreateOrUpdateFilterTable extends Table {
|
||||
private void setCollapsibleColumns() {
|
||||
setColumnCollapsed(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY, true);
|
||||
setColumnCollapsed(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, true);
|
||||
|
||||
setColumnCollapsed(ASSIGN_DIST_SET, true);
|
||||
setColumnCollapsed(INSTALL_DIST_SET, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,10 +182,13 @@ public class CreateOrUpdateFilterTable extends Table {
|
||||
container.addContainerProperty(SPUILabelDefinitions.VAR_CREATED_DATE, Date.class, null);
|
||||
container.addContainerProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY, String.class, null, false, true);
|
||||
container.addContainerProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, String.class, null, false, true);
|
||||
container.addContainerProperty(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER, String.class, "");
|
||||
container.addContainerProperty(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_NAME_VER, String.class, null);
|
||||
container.addContainerProperty(SPUILabelDefinitions.VAR_TARGET_STATUS, TargetUpdateStatus.class, null);
|
||||
container.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, "", false, true);
|
||||
|
||||
container.addContainerProperty(ASSIGN_DIST_SET, DistributionSet.class, null, false, true);
|
||||
container.addContainerProperty(INSTALL_DIST_SET, DistributionSet.class, null, false, true);
|
||||
container.addContainerProperty(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER, String.class, "");
|
||||
container.addContainerProperty(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_NAME_VER, String.class, null);
|
||||
}
|
||||
|
||||
private List<TableColumn> getVisbleColumns() {
|
||||
@@ -186,12 +199,9 @@ public class CreateOrUpdateFilterTable extends Table {
|
||||
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY, i18n.get("header.modifiedBy"), 0.1F));
|
||||
columnList.add(
|
||||
new TableColumn(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE, i18n.get("header.modifiedDate"), 0.1F));
|
||||
columnList.add(new TableColumn(SPUILabelDefinitions.ASSIGNED_DISTRIBUTION_NAME_VER,
|
||||
i18n.get("header.assigned.ds"), 0.125F));
|
||||
columnList.add(new TableColumn(SPUILabelDefinitions.INSTALLED_DISTRIBUTION_NAME_VER,
|
||||
i18n.get("header.installed.ds"), 0.125F));
|
||||
columnList.add(new TableColumn(SPUILabelDefinitions.VAR_DESC, i18n.get("header.description"), 0.1F));
|
||||
columnList.add(new TableColumn(SPUILabelDefinitions.STATUS_ICON, i18n.get("header.status"), 0.1F));
|
||||
|
||||
return columnList;
|
||||
}
|
||||
|
||||
@@ -244,4 +254,5 @@ public class CreateOrUpdateFilterTable extends Table {
|
||||
populateTableData();
|
||||
eventBus.publish(this, CustomFilterUIEvent.UPDATE_TARGET_FILTER_SEARCH_ICON);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.ProxyTarget;
|
||||
import org.eclipse.hawkbit.ui.filtermanagement.state.FilterManagementUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
@@ -118,22 +118,9 @@ public class CustomTargetBeanQuery extends AbstractBeanQuery<ProxyTarget> {
|
||||
prxyTarget.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(targ.getLastModifiedAt()));
|
||||
prxyTarget.setCreatedDate(SPDateTimeUtil.getFormattedDate(targ.getCreatedAt()));
|
||||
prxyTarget.setCreatedAt(targ.getCreatedAt());
|
||||
prxyTarget.setCreatedByUser(HawkbitCommonUtil.getIMUser(targ.getCreatedBy()));
|
||||
prxyTarget.setModifiedByUser(HawkbitCommonUtil.getIMUser(targ.getLastModifiedBy()));
|
||||
final Target target = getTargetManagement().findTargetByControllerIDWithDetails(targ.getControllerId());
|
||||
final DistributionSet installedDistributionSet = target.getTargetInfo().getInstalledDistributionSet();
|
||||
prxyTarget.setInstalledDistributionSet(installedDistributionSet);
|
||||
final DistributionSet assignedDistributionSet = target.getAssignedDistributionSet();
|
||||
prxyTarget.setAssignedDistributionSet(assignedDistributionSet);
|
||||
prxyTarget.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(targ));
|
||||
prxyTarget.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(targ));
|
||||
|
||||
if (null != assignedDistributionSet) {
|
||||
prxyTarget.setAssignedDistNameVersion(HawkbitCommonUtil.getFormattedNameVersion(
|
||||
assignedDistributionSet.getName(), assignedDistributionSet.getVersion()));
|
||||
}
|
||||
if (null != installedDistributionSet) {
|
||||
prxyTarget.setInstalledDistNameVersion(HawkbitCommonUtil.getFormattedNameVersion(
|
||||
installedDistributionSet.getName(), installedDistributionSet.getVersion()));
|
||||
}
|
||||
prxyTarget.setUpdateStatus(targ.getTargetInfo().getUpdateStatus());
|
||||
prxyTarget.setLastTargetQuery(targ.getTargetInfo().getLastTargetQuery());
|
||||
prxyTarget.setTargetInfo(targ.getTargetInfo());
|
||||
|
||||
@@ -96,7 +96,8 @@ public class FilterManagementView extends VerticalLayout implements View {
|
||||
} else if (custFilterUIEvent == CustomFilterUIEvent.CREATE_NEW_FILTER_CLICK
|
||||
|| custFilterUIEvent == CustomFilterUIEvent.FILTER_TARGET_BY_QUERY) {
|
||||
this.getUI().access(() -> viewCreateTargetFilterLayout());
|
||||
} else if (custFilterUIEvent == CustomFilterUIEvent.EXIT_CREATE_OR_UPDATE_FILTRER_VIEW) {
|
||||
} else if (custFilterUIEvent == CustomFilterUIEvent.EXIT_CREATE_OR_UPDATE_FILTRER_VIEW
|
||||
|| custFilterUIEvent == CustomFilterUIEvent.SHOW_FILTER_MANAGEMENT) {
|
||||
UI.getCurrent().access(() -> viewListView());
|
||||
}
|
||||
}
|
||||
@@ -121,11 +122,11 @@ public class FilterManagementView extends VerticalLayout implements View {
|
||||
tableHeaderLayout.setComponentAlignment(createNewFilterHeader, Alignment.TOP_CENTER);
|
||||
tableHeaderLayout.addComponent(createNewFilterTable);
|
||||
tableHeaderLayout.setComponentAlignment(createNewFilterTable, Alignment.TOP_CENTER);
|
||||
tableHeaderLayout.setExpandRatio(createNewFilterTable, 1.0f);
|
||||
tableHeaderLayout.setExpandRatio(createNewFilterTable, 1.0F);
|
||||
|
||||
addComponent(tableHeaderLayout);
|
||||
setComponentAlignment(tableHeaderLayout, Alignment.TOP_CENTER);
|
||||
setExpandRatio(tableHeaderLayout, 1.0f);
|
||||
setExpandRatio(tableHeaderLayout, 1.0F);
|
||||
|
||||
final HorizontalLayout targetsCountmessageLabelLayout = addTargetFilterMessageLabel();
|
||||
addComponent(targetsCountmessageLabelLayout);
|
||||
@@ -135,17 +136,17 @@ public class FilterManagementView extends VerticalLayout implements View {
|
||||
|
||||
private void viewListView() {
|
||||
removeAllComponents();
|
||||
final VerticalLayout tableHeaderLayout = new VerticalLayout();
|
||||
tableHeaderLayout.setSizeFull();
|
||||
tableHeaderLayout.setSpacing(false);
|
||||
tableHeaderLayout.setMargin(false);
|
||||
tableHeaderLayout.setStyleName("table-layout");
|
||||
tableHeaderLayout.addComponent(targetFilterHeader);
|
||||
tableHeaderLayout.setComponentAlignment(targetFilterHeader, Alignment.TOP_CENTER);
|
||||
tableHeaderLayout.addComponent(targetFilterTable);
|
||||
tableHeaderLayout.setComponentAlignment(targetFilterTable, Alignment.TOP_CENTER);
|
||||
tableHeaderLayout.setExpandRatio(targetFilterTable, 1.0f);
|
||||
addComponent(tableHeaderLayout);
|
||||
final VerticalLayout tableListViewLayout = new VerticalLayout();
|
||||
tableListViewLayout.setSizeFull();
|
||||
tableListViewLayout.setSpacing(false);
|
||||
tableListViewLayout.setMargin(false);
|
||||
tableListViewLayout.setStyleName("table-layout");
|
||||
tableListViewLayout.addComponent(targetFilterHeader);
|
||||
tableListViewLayout.setComponentAlignment(targetFilterHeader, Alignment.TOP_CENTER);
|
||||
tableListViewLayout.addComponent(targetFilterTable);
|
||||
tableListViewLayout.setComponentAlignment(targetFilterTable, Alignment.TOP_CENTER);
|
||||
tableListViewLayout.setExpandRatio(targetFilterTable, 1.0F);
|
||||
addComponent(tableListViewLayout);
|
||||
}
|
||||
|
||||
private HorizontalLayout addTargetFilterMessageLabel() {
|
||||
|
||||
@@ -31,10 +31,7 @@ import cz.jirutka.rsql.parser.RSQLParserException;
|
||||
*
|
||||
* Validates the target filter query.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public final class FilterQueryValidation {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(FilterQueryValidation.class);
|
||||
@@ -103,6 +100,9 @@ public final class FilterQueryValidation {
|
||||
* @param expectedTokens
|
||||
* @return
|
||||
*/
|
||||
// Exception squid:S2095 - see
|
||||
// https://jira.sonarsource.com/browse/SONARJAVA-1478
|
||||
@SuppressWarnings({ "squid:S2095" })
|
||||
public static List<String> processExpectedTokens(final List<Integer> expectedTokens) {
|
||||
final List<String> expectToken = new ArrayList<>();
|
||||
if (expectedTokens.size() == 2 && expectedTokens.contains(9) && expectedTokens.contains(4)) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.ProxyTargetFilter;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
@@ -93,9 +94,9 @@ public class TargetFilterBeanQuery extends AbstractBeanQuery<ProxyTargetFilter>
|
||||
proxyTarFilter.setName(tarFilterQuery.getName());
|
||||
proxyTarFilter.setId(tarFilterQuery.getId());
|
||||
proxyTarFilter.setCreatedDate(SPDateTimeUtil.getFormattedDate(tarFilterQuery.getCreatedAt()));
|
||||
proxyTarFilter.setCreatedBy(HawkbitCommonUtil.getIMUser(tarFilterQuery.getCreatedBy()));
|
||||
proxyTarFilter.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(tarFilterQuery));
|
||||
proxyTarFilter.setModifiedDate(SPDateTimeUtil.getFormattedDate(tarFilterQuery.getLastModifiedAt()));
|
||||
proxyTarFilter.setLastModifiedBy(HawkbitCommonUtil.getIMUser(tarFilterQuery.getLastModifiedBy()));
|
||||
proxyTarFilter.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(tarFilterQuery));
|
||||
proxyTarFilter.setQuery(tarFilterQuery.getQuery());
|
||||
proxyTargetFilter.add(proxyTarFilter);
|
||||
}
|
||||
|
||||
@@ -15,5 +15,5 @@ package org.eclipse.hawkbit.ui.filtermanagement.event;
|
||||
*
|
||||
*/
|
||||
public enum CustomFilterUIEvent {
|
||||
FILTER_TARGET_BY_QUERY, FILTER_BY_CUST_FILTER_TEXT, FILTER_BY_CUST_FILTER_TEXT_REMOVE, CREATE_NEW_FILTER_CLICK, EXIT_CREATE_OR_UPDATE_FILTRER_VIEW, TARGET_FILTER_DETAIL_VIEW, TARGET_DETAILS_VIEW, CREATE_TARGET_FILTER_QUERY, UPDATED_TARGET_FILTER_QUERY, UPDATE_TARGET_FILTER_SEARCH_ICON
|
||||
FILTER_TARGET_BY_QUERY, FILTER_BY_CUST_FILTER_TEXT, FILTER_BY_CUST_FILTER_TEXT_REMOVE, CREATE_NEW_FILTER_CLICK, EXIT_CREATE_OR_UPDATE_FILTRER_VIEW, TARGET_FILTER_DETAIL_VIEW, TARGET_DETAILS_VIEW, CREATE_TARGET_FILTER_QUERY, UPDATED_TARGET_FILTER_QUERY, UPDATE_TARGET_FILTER_SEARCH_ICON, SHOW_FILTER_MANAGEMENT
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ public class LoginView extends VerticalLayout implements View {
|
||||
final String linkStyle = "v-link";
|
||||
|
||||
if (!uiProperties.getLinks().getDocumentation().getRoot().isEmpty()) {
|
||||
final Link docuLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_DOCUMENATION,
|
||||
final Link docuLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_DOCUMENTATION,
|
||||
i18n.get("link.documentation.name"), uiProperties.getLinks().getDocumentation().getRoot(),
|
||||
FontAwesome.QUESTION_CIRCLE, "_blank", linkStyle, true);
|
||||
links.addComponent(docuLink);
|
||||
|
||||
@@ -145,11 +145,12 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
|
||||
setSizeUndefined();
|
||||
addComponents(madatoryLabel, distsetTypeNameComboBox, distNameTextField, distVersionTextField, descTextArea,
|
||||
reqMigStepCheckbox);
|
||||
|
||||
|
||||
addComponent(buttonsLayout);
|
||||
setComponentAlignment(madatoryLabel, Alignment.MIDDLE_LEFT);
|
||||
|
||||
}
|
||||
distNameTextField.focus();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create required UI components.
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.DistributionSetFilter.DistributionSetFilte
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.ProxyDistribution;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
@@ -129,8 +130,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery<ProxyDistribution>
|
||||
proxyDistribution.setCreatedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getCreatedAt()));
|
||||
proxyDistribution.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getLastModifiedAt()));
|
||||
proxyDistribution.setDescription(distributionSet.getDescription());
|
||||
proxyDistribution.setCreatedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getCreatedBy()));
|
||||
proxyDistribution.setModifiedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getLastModifiedBy()));
|
||||
proxyDistribution.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(distributionSet));
|
||||
proxyDistribution.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(distributionSet));
|
||||
proxyDistribution.setNameVersion(
|
||||
HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion()));
|
||||
proxyDistributions.add(proxyDistribution);
|
||||
|
||||
@@ -43,10 +43,6 @@ import com.vaadin.ui.themes.ValoTheme;
|
||||
@SpringComponent
|
||||
@VaadinSessionScope
|
||||
public class CreateUpdateDistributionTagLayoutWindow extends CreateUpdateTagLayout {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 444276149954167545L;
|
||||
|
||||
@Autowired
|
||||
@@ -288,16 +284,22 @@ public class CreateUpdateDistributionTagLayoutWindow extends CreateUpdateTagLayo
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onDistributionSetTagCreatedBulkEvent(final DistributionSetTagCreatedBulkEvent event) {
|
||||
populateTagNameCombo();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onDistributionSetTagDeletedEvent(final DistributionSetTagDeletedEvent event) {
|
||||
populateTagNameCombo();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onDistributionSetTagUpdateEvent(final DistributionSetTagUpdateEvent event) {
|
||||
populateTagNameCombo();
|
||||
}
|
||||
|
||||
@@ -61,16 +61,22 @@ public class DistributionTagButtons extends AbstractFilterButtons {
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onDistributionSetTagCreatedBulkEvent(final DistributionSetTagCreatedBulkEvent event) {
|
||||
refreshTagTable();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onDistributionSetTagDeletedEvent(final DistributionSetTagDeletedEvent event) {
|
||||
refreshTagTable();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onDistributionSetTagUpdateEvent(final DistributionSetTagUpdateEvent event) {
|
||||
refreshTagTable();
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ public abstract class CreateUpdateTagLayout extends CustomComponent implements C
|
||||
tagName = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_NAME,
|
||||
true, "", i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
||||
tagName.setId(SPUIDefinitions.NEW_TARGET_TAG_NAME);
|
||||
|
||||
|
||||
tagDesc = SPUIComponentProvider.getTextArea("", ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TAG_DESC,
|
||||
false, "", i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
|
||||
|
||||
@@ -237,7 +237,8 @@ public abstract class CreateUpdateTagLayout extends CustomComponent implements C
|
||||
fieldLayout.addComponent(madatoryLabel);
|
||||
fieldLayout.addComponent(tagName);
|
||||
fieldLayout.addComponent(tagDesc);
|
||||
|
||||
|
||||
|
||||
final HorizontalLayout colorLabelLayout = new HorizontalLayout();
|
||||
colorLabelLayout.addComponents(colorLabel, tagColorPreviewBtn);
|
||||
fieldLayout.addComponent(colorLabelLayout);
|
||||
@@ -257,8 +258,8 @@ public abstract class CreateUpdateTagLayout extends CustomComponent implements C
|
||||
|
||||
mainLayout = new HorizontalLayout();
|
||||
mainLayout.addComponent(fieldButtonLayout);
|
||||
|
||||
setCompositionRoot(mainLayout);
|
||||
tagName.focus();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ public class TargetAddUpdateWindowLayout extends CustomComponent {
|
||||
madatoryLabel.setVisible(Boolean.FALSE);
|
||||
}
|
||||
mainLayout.addComponents(madatoryLabel, controllerIDTextField, nameTextField, descTextArea, buttonsLayout);
|
||||
|
||||
nameTextField.focus();
|
||||
}
|
||||
|
||||
private void addListeners() {
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.ProxyTarget;
|
||||
import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
@@ -130,8 +131,8 @@ public class TargetBeanQuery extends AbstractBeanQuery<ProxyTarget> {
|
||||
prxyTarget.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(targ.getLastModifiedAt()));
|
||||
prxyTarget.setCreatedDate(SPDateTimeUtil.getFormattedDate(targ.getCreatedAt()));
|
||||
prxyTarget.setCreatedAt(targ.getCreatedAt());
|
||||
prxyTarget.setCreatedByUser(HawkbitCommonUtil.getIMUser(targ.getCreatedBy()));
|
||||
prxyTarget.setModifiedByUser(HawkbitCommonUtil.getIMUser(targ.getLastModifiedBy()));
|
||||
prxyTarget.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(targ));
|
||||
prxyTarget.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(targ));
|
||||
|
||||
if (pinnedDistId == null) {
|
||||
prxyTarget.setInstalledDistributionSet(null);
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.ui.common.ManagmentEntityState;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.common.table.AbstractTable;
|
||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||
import org.eclipse.hawkbit.ui.filter.FilterExpression;
|
||||
@@ -51,6 +52,7 @@ 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.TargetTableFilters;
|
||||
import org.eclipse.hawkbit.ui.utils.AssignInstalledDSTooltipGenerator;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
|
||||
@@ -136,6 +138,7 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> implements
|
||||
addActionHandler(this);
|
||||
actionSelectAll = new ShortcutAction(i18n.get("action.target.table.selectall"));
|
||||
actionUnSelectAll = new ShortcutAction(i18n.get("action.target.table.clear"));
|
||||
setItemDescriptionGenerator(new AssignInstalledDSTooltipGenerator());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,7 +332,7 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> implements
|
||||
if (!isMaximized()) {
|
||||
columnList.add(new TableColumn(SPUIDefinitions.TARGET_STATUS_POLL_TIME, "", 0.0F));
|
||||
columnList.add(new TableColumn(SPUIDefinitions.TARGET_STATUS_PIN_TOGGLE_ICON, "", 0.0F));
|
||||
}
|
||||
}
|
||||
return columnList;
|
||||
|
||||
}
|
||||
@@ -739,7 +742,7 @@ public class TargetTable extends AbstractTable<Target, TargetIdName> implements
|
||||
.setValue(updatedTarget.getTargetInfo().getLastTargetQuery());
|
||||
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_BY)
|
||||
.setValue(HawkbitCommonUtil.getIMUser(updatedTarget.getLastModifiedBy()));
|
||||
.setValue(UserDetailsFormatter.loadAndFormatLastModifiedBy(updatedTarget));
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_LAST_MODIFIED_DATE)
|
||||
.setValue(SPDateTimeUtil.getFormattedDate(updatedTarget.getLastModifiedAt()));
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_DESC).setValue(updatedTarget.getDescription());
|
||||
|
||||
@@ -85,16 +85,22 @@ public class CreateUpdateTargetTagLayout extends CreateUpdateTagLayout {
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onEventTargetTagCreated(final TargetTagCreatedBulkEvent event) {
|
||||
populateTagNameCombo();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onEventTargetDeletedEvent(final TargetTagDeletedEvent event) {
|
||||
populateTagNameCombo();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onEventTargetTagUpdateEvent(final TargetTagUpdateEvent event) {
|
||||
populateTagNameCombo();
|
||||
}
|
||||
@@ -144,7 +150,7 @@ public class CreateUpdateTargetTagLayout extends CreateUpdateTagLayout {
|
||||
final TargetTag existingTag = tagManagement.findTargetTag(tagName.getValue());
|
||||
if (optiongroup.getValue().equals(createTagNw)) {
|
||||
if (!checkIsDuplicate(existingTag)) {
|
||||
crateNewTag();
|
||||
createNewTag();
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -182,8 +188,8 @@ public class CreateUpdateTargetTagLayout extends CreateUpdateTagLayout {
|
||||
/**
|
||||
* Create new tag.
|
||||
*/
|
||||
private void crateNewTag() {
|
||||
final String colorPicked = getColorPickedSting();
|
||||
private void createNewTag() {
|
||||
final String colorPicked = getColorPickedString();
|
||||
final String tagNameValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagName.getValue());
|
||||
final String tagDescValue = HawkbitCommonUtil.trimAndNullIfEmpty(tagDesc.getValue());
|
||||
if (null != tagNameValue) {
|
||||
@@ -214,7 +220,7 @@ public class CreateUpdateTargetTagLayout extends CreateUpdateTagLayout {
|
||||
if (null != nameUpdateValue) {
|
||||
targetObj.setName(nameUpdateValue);
|
||||
targetObj.setDescription(null != descUpdateValue ? descUpdateValue : null);
|
||||
targetObj.setColour(getColorPickedSting());
|
||||
targetObj.setColour(getColorPickedString());
|
||||
tagManagement.updateTargetTag(targetObj);
|
||||
uiNotification.displaySuccess(i18n.get("message.update.success", new Object[] { targetObj.getName() }));
|
||||
closeWindow();
|
||||
@@ -244,7 +250,7 @@ public class CreateUpdateTargetTagLayout extends CreateUpdateTagLayout {
|
||||
*
|
||||
* @return String of color picked value.
|
||||
*/
|
||||
private String getColorPickedSting() {
|
||||
private String getColorPickedString() {
|
||||
return "rgb(" + getSelPreview().getColor().getRed() + "," + getSelPreview().getColor().getGreen() + ","
|
||||
+ getSelPreview().getColor().getBlue() + ")";
|
||||
}
|
||||
|
||||
@@ -267,16 +267,22 @@ public class TargetTagFilterButtons extends AbstractFilterButtons {
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onEvent(final TargetTagUpdateEvent event) {
|
||||
refreshContainer();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onEventTargetTagCreated(final TargetTagCreatedBulkEvent event) {
|
||||
refreshContainer();
|
||||
}
|
||||
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
// Exception squid:S1172 - event not needed
|
||||
@SuppressWarnings({ "squid:S1172" })
|
||||
void onEventTargetDeletedEvent(final TargetTagDeletedEvent event) {
|
||||
refreshContainer();
|
||||
}
|
||||
|
||||
@@ -18,23 +18,20 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.hawkbit.HawkbitServerProperties;
|
||||
import org.eclipse.hawkbit.im.authentication.PermissionService;
|
||||
import org.eclipse.hawkbit.im.authentication.UserPrincipal;
|
||||
import org.eclipse.hawkbit.ui.UiProperties;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
|
||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
|
||||
import com.vaadin.server.FontAwesome;
|
||||
import com.vaadin.server.Page;
|
||||
import com.vaadin.server.ThemeResource;
|
||||
import com.vaadin.server.VaadinService;
|
||||
import com.vaadin.shared.ui.label.ContentMode;
|
||||
import com.vaadin.spring.annotation.SpringComponent;
|
||||
import com.vaadin.spring.annotation.UIScope;
|
||||
@@ -115,9 +112,9 @@ public final class DashboardMenu extends CustomComponent {
|
||||
final VerticalLayout links = buildLinksAndVersion();
|
||||
menus.addComponent(links);
|
||||
menus.setComponentAlignment(links, Alignment.BOTTOM_CENTER);
|
||||
menus.setExpandRatio(links, 1.0f);
|
||||
menus.setExpandRatio(links, 1.0F);
|
||||
menuContent.addComponent(menus);
|
||||
menuContent.setExpandRatio(menus, 1.0f);
|
||||
menuContent.setExpandRatio(menus, 1.0F);
|
||||
|
||||
dashboardMenuLayout.addComponent(menuContent);
|
||||
return dashboardMenuLayout;
|
||||
@@ -139,7 +136,7 @@ public final class DashboardMenu extends CustomComponent {
|
||||
final Label logo = new Label("<strong>" + i18n.get("menu.title") + "</strong>", ContentMode.HTML);
|
||||
logo.setSizeUndefined();
|
||||
final HorizontalLayout logoWrapper = new HorizontalLayout(logo);
|
||||
logoWrapper.setComponentAlignment(logo, Alignment.MIDDLE_CENTER);
|
||||
logoWrapper.setComponentAlignment(logo, Alignment.TOP_CENTER);
|
||||
logoWrapper.addStyleName("valo-menu-title");
|
||||
return logoWrapper;
|
||||
}
|
||||
@@ -151,7 +148,7 @@ public final class DashboardMenu extends CustomComponent {
|
||||
final String linkStyle = "v-link";
|
||||
|
||||
if (!uiProperties.getLinks().getDocumentation().getRoot().isEmpty()) {
|
||||
final Link docuLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_DOCUMENATION,
|
||||
final Link docuLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_DOCUMENTATION,
|
||||
i18n.get("link.documentation.name"), uiProperties.getLinks().getDocumentation().getRoot(),
|
||||
FontAwesome.QUESTION_CIRCLE, "_blank", linkStyle, true);
|
||||
docuLink.setDescription(i18n.get("link.documentation.name"));
|
||||
@@ -189,63 +186,27 @@ public final class DashboardMenu extends CustomComponent {
|
||||
return links;
|
||||
}
|
||||
|
||||
private UserDetails getCurrentUser() {
|
||||
final SecurityContext context = (SecurityContext) VaadinService.getCurrentRequest().getWrappedSession()
|
||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
return (UserDetails) context.getAuthentication().getPrincipal();
|
||||
}
|
||||
|
||||
private Component buildUserMenu() {
|
||||
final MenuBar settings = new MenuBar();
|
||||
settings.addStyleName("user-menu");
|
||||
final UserDetails user = getCurrentUser();
|
||||
settings.setHtmlContentAllowed(true);
|
||||
final MenuItem settingsItem = settings.addItem("", new ThemeResource("images/profile-pic-57px.jpg"), null);
|
||||
if (user instanceof UserPrincipal
|
||||
&& (((UserPrincipal) user).getFirstname() != null || ((UserPrincipal) user).getLastname() != null)) {
|
||||
settingsItem.setText(trimTanent(((UserPrincipal) user).getTenant()) + "\n"
|
||||
+ concateFNameLName(((UserPrincipal) user).getFirstname(), ((UserPrincipal) user).getLastname()));
|
||||
settingsItem.setDescription(
|
||||
((UserPrincipal) user).getFirstname() + " / " + ((UserPrincipal) user).getLastname());
|
||||
} else if (user instanceof UserPrincipal) {
|
||||
if (((UserPrincipal) user).getLoginname().length() > 10) {
|
||||
settingsItem.setText(trimTanent(((UserPrincipal) user).getTenant()) + "\n"
|
||||
+ ((UserPrincipal) user).getLoginname().substring(0, 10) + "..");
|
||||
} else {
|
||||
settingsItem.setText(
|
||||
trimTanent(((UserPrincipal) user).getTenant()) + "\n" + ((UserPrincipal) user).getLoginname());
|
||||
}
|
||||
settingsItem.setDescription(((UserPrincipal) user).getLoginname());
|
||||
} else if (user != null) {
|
||||
settingsItem.setText(user.getUsername());
|
||||
settingsItem.setDescription(user.getUsername());
|
||||
|
||||
final String formattedTenant = UserDetailsFormatter.formatCurrentTenant();
|
||||
final String formattedUsername = UserDetailsFormatter.formatCurrentUsername();
|
||||
String tenantAndUsernameHtml = "";
|
||||
if (!StringUtils.isEmpty(formattedTenant)) {
|
||||
tenantAndUsernameHtml += formattedTenant + "<br>";
|
||||
}
|
||||
tenantAndUsernameHtml += formattedUsername;
|
||||
settingsItem.setText(tenantAndUsernameHtml);
|
||||
settingsItem.setDescription(formattedUsername);
|
||||
settingsItem.setStyleName("user-menuitem");
|
||||
|
||||
settingsItem.addItem("Sign Out", selectedItem -> Page.getCurrent().setLocation("/UI/logout"));
|
||||
return settings;
|
||||
}
|
||||
|
||||
private String concateFNameLName(final String fName, final String lName) {
|
||||
final StringBuilder userName = new StringBuilder();
|
||||
if (fName != null && fName.length() > 6) {
|
||||
userName.append(fName.substring(0, 6) + ".." + ", ");
|
||||
} else {
|
||||
userName.append(fName).append(", ");
|
||||
}
|
||||
if (lName != null && lName.length() > 6) {
|
||||
userName.append(lName.substring(0, 6) + "..");
|
||||
} else {
|
||||
userName.append(lName);
|
||||
}
|
||||
return userName.toString();
|
||||
}
|
||||
|
||||
private String trimTanent(final String tanent) {
|
||||
if (tanent != null && tanent.length() > 8) {
|
||||
return tanent.substring(0, 8) + "..";
|
||||
}
|
||||
return tanent;
|
||||
}
|
||||
|
||||
private Component buildToggleButton() {
|
||||
final Button valoMenuToggleButton = new Button("Menu", (ClickListener) event -> {
|
||||
if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) {
|
||||
@@ -264,7 +225,7 @@ public final class DashboardMenu extends CustomComponent {
|
||||
private VerticalLayout buildMenuItems() {
|
||||
final VerticalLayout menuItemsLayout = new VerticalLayout();
|
||||
menuItemsLayout.addStyleName("valo-menuitems");
|
||||
menuItemsLayout.setHeight(100.0f, Unit.PERCENTAGE);
|
||||
menuItemsLayout.setHeight(100.0F, Unit.PERCENTAGE);
|
||||
|
||||
final List<DashboardMenuItem> accessibleViews = getAccessibleViews();
|
||||
if (accessibleViews.isEmpty()) {
|
||||
|
||||
@@ -209,6 +209,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
|
||||
actionTypeOptionGroupLayout, linkToHelp, getSaveDiscardButtonLayout());
|
||||
mainLayout.setComponentAlignment(linkToHelp, Alignment.BOTTOM_RIGHT);
|
||||
setCompositionRoot(mainLayout);
|
||||
rolloutName.focus();
|
||||
}
|
||||
|
||||
private HorizontalLayout getGroupDetailsLayout() {
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFilter.DistributionSetFilterBuilder;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.ProxyDistribution;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
@@ -62,7 +63,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery<ProxyDistribution>
|
||||
sort = new Sort(sortStates[0] ? Direction.ASC : Direction.DESC, (String) sortPropertyIds[0]);
|
||||
// Add sort
|
||||
for (int distId = 1; distId < sortPropertyIds.length; distId++) {
|
||||
sort.and(new Sort(sortStates[distId] ? Direction.ASC : Direction.DESC, (String) sortPropertyIds[distId]));
|
||||
sort.and(new Sort(sortStates[distId] ? Direction.ASC : Direction.DESC,
|
||||
(String) sortPropertyIds[distId]));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,8 +105,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery<ProxyDistribution>
|
||||
final List<ProxyDistribution> proxyDistributions = new ArrayList<>();
|
||||
for (final DistributionSet distributionSet : distBeans) {
|
||||
final ProxyDistribution proxyDistribution = new ProxyDistribution();
|
||||
proxyDistribution.setName(HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(),
|
||||
distributionSet.getVersion()));
|
||||
proxyDistribution.setName(
|
||||
HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion()));
|
||||
proxyDistribution.setDescription(distributionSet.getDescription());
|
||||
proxyDistribution.setDistId(distributionSet.getId());
|
||||
proxyDistribution.setId(distributionSet.getId());
|
||||
@@ -112,8 +114,8 @@ public class DistributionBeanQuery extends AbstractBeanQuery<ProxyDistribution>
|
||||
proxyDistribution.setCreatedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getCreatedAt()));
|
||||
proxyDistribution.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(distributionSet.getLastModifiedAt()));
|
||||
proxyDistribution.setDescription(distributionSet.getDescription());
|
||||
proxyDistribution.setCreatedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getCreatedBy()));
|
||||
proxyDistribution.setModifiedByUser(HawkbitCommonUtil.getIMUser(distributionSet.getLastModifiedBy()));
|
||||
proxyDistribution.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(distributionSet));
|
||||
proxyDistribution.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(distributionSet));
|
||||
proxyDistribution.setIsComplete(distributionSet.isComplete());
|
||||
proxyDistributions.add(proxyDistribution);
|
||||
}
|
||||
|
||||
@@ -8,12 +8,16 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.rollout.rollout;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
|
||||
import com.vaadin.server.FontAwesome;
|
||||
|
||||
/**
|
||||
* Proxy rollout with suctome properties.
|
||||
* Proxy rollout with custom properties.
|
||||
*
|
||||
*/
|
||||
public class ProxyRollout extends Rollout {
|
||||
@@ -30,8 +34,92 @@ public class ProxyRollout extends Rollout {
|
||||
|
||||
private Boolean isActionRecieved = Boolean.FALSE;
|
||||
|
||||
private Boolean isRequiredMigrationStep = Boolean.FALSE;
|
||||
|
||||
private String totalTargetsCount;
|
||||
|
||||
|
||||
private RolloutRendererData rolloutRendererData;
|
||||
|
||||
private String discription;
|
||||
|
||||
private String type;
|
||||
|
||||
private Set<SoftwareModule> swModules;
|
||||
|
||||
/**
|
||||
* @return the isRequiredMigrationStep
|
||||
*/
|
||||
|
||||
public Boolean getIsRequiredMigrationStep() {
|
||||
return isRequiredMigrationStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isRequiredMigrationStep
|
||||
* the isRequiredMigrationStep to set
|
||||
*/
|
||||
|
||||
public void setIsRequiredMigrationStep(Boolean isRequiredMigrationStep) {
|
||||
this.isRequiredMigrationStep = isRequiredMigrationStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the discription
|
||||
*/
|
||||
|
||||
public String getDiscription() {
|
||||
return discription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param discription
|
||||
* the discription to set
|
||||
*/
|
||||
|
||||
public void setDiscription(String discription) {
|
||||
this.discription = discription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the type to set
|
||||
*/
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the Set of Software modules
|
||||
*/
|
||||
public Set<SoftwareModule> getSwModules() {
|
||||
return swModules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param swModules
|
||||
* Set<SoftwareModule> to set
|
||||
*/
|
||||
public void setSwModules(Set<SoftwareModule> swModules) {
|
||||
this.swModules = swModules;
|
||||
}
|
||||
|
||||
public RolloutRendererData getRolloutRendererData() {
|
||||
return rolloutRendererData;
|
||||
}
|
||||
|
||||
public void setRolloutRendererData(RolloutRendererData rendererData) {
|
||||
this.rolloutRendererData = rendererData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the distributionSetNameVersion
|
||||
*/
|
||||
@@ -121,10 +209,9 @@ public class ProxyRollout extends Rollout {
|
||||
public void setTotalTargetsCount(final String totalTargetsCount) {
|
||||
this.totalTargetsCount = totalTargetsCount;
|
||||
}
|
||||
|
||||
|
||||
public String getAction() {
|
||||
|
||||
public String getAction() {
|
||||
return FontAwesome.CIRCLE_O.getHtml();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
@@ -119,22 +121,29 @@ public class RolloutBeanQuery extends AbstractBeanQuery<ProxyRollout> {
|
||||
proxyRollout.setName(rollout.getName());
|
||||
proxyRollout.setDescription(rollout.getDescription());
|
||||
final DistributionSet distributionSet = rollout.getDistributionSet();
|
||||
proxyRollout.setDistributionSetNameVersion(HawkbitCommonUtil.getFormattedNameVersion(
|
||||
distributionSet.getName(), distributionSet.getVersion()));
|
||||
proxyRollout.setDistributionSetNameVersion(
|
||||
HawkbitCommonUtil.getFormattedNameVersion(distributionSet.getName(), distributionSet.getVersion()));
|
||||
proxyRollout.setDistributionSet(distributionSet);
|
||||
proxyRollout.setNumberOfGroups(Long.valueOf(rollout.getRolloutGroups().size()));
|
||||
proxyRollout.setCreatedDate(SPDateTimeUtil.getFormattedDate(rollout.getCreatedAt()));
|
||||
proxyRollout.setModifiedDate(SPDateTimeUtil.getFormattedDate(rollout.getLastModifiedAt()));
|
||||
proxyRollout.setCreatedBy(HawkbitCommonUtil.getIMUser(rollout.getCreatedBy()));
|
||||
proxyRollout.setLastModifiedBy(HawkbitCommonUtil.getIMUser(rollout.getLastModifiedBy()));
|
||||
proxyRollout.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rollout));
|
||||
proxyRollout.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rollout));
|
||||
proxyRollout.setForcedTime(rollout.getForcedTime());
|
||||
proxyRollout.setId(rollout.getId());
|
||||
proxyRollout.setStatus(rollout.getStatus());
|
||||
proxyRollout
|
||||
.setRolloutRendererData(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString()));
|
||||
|
||||
final TotalTargetCountStatus totalTargetCountActionStatus = rollout.getTotalTargetCountStatus();
|
||||
proxyRollout.setTotalTargetCountStatus(totalTargetCountActionStatus);
|
||||
proxyRollout.setTotalTargetsCount(String.valueOf(rollout.getTotalTargets()));
|
||||
|
||||
|
||||
proxyRollout.setDescription(distributionSet.getDescription());
|
||||
proxyRollout.setType(distributionSet.getType().getName());
|
||||
proxyRollout.setIsRequiredMigrationStep(distributionSet.isRequiredMigrationStep());
|
||||
proxyRollout.setSwModules(distributionSet.getModules());
|
||||
|
||||
proxyRolloutList.add(proxyRollout);
|
||||
}
|
||||
return proxyRolloutList;
|
||||
@@ -148,7 +157,8 @@ public class RolloutBeanQuery extends AbstractBeanQuery<ProxyRollout> {
|
||||
* .util.List, java.util.List, java.util.List)
|
||||
*/
|
||||
@Override
|
||||
protected void saveBeans(final List<ProxyRollout> arg0, final List<ProxyRollout> arg1, final List<ProxyRollout> arg2) {
|
||||
protected void saveBeans(final List<ProxyRollout> arg0, final List<ProxyRollout> arg1,
|
||||
final List<ProxyRollout> arg2) {
|
||||
/**
|
||||
* CRUD operations on Target will be done through repository methods
|
||||
*/
|
||||
|
||||
@@ -8,23 +8,31 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.ui.rollout.rollout;
|
||||
|
||||
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_LI_CLOSE_TAG;
|
||||
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_LI_OPEN_TAG;
|
||||
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_UL_CLOSE_TAG;
|
||||
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.HTML_UL_OPEN_TAG;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.RolloutChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlLabelRenderer;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer;
|
||||
import org.eclipse.hawkbit.ui.rollout.DistributionBarHelper;
|
||||
import org.eclipse.hawkbit.ui.rollout.StatusFontIcon;
|
||||
import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent;
|
||||
@@ -77,6 +85,13 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
|
||||
private static final String START_OPTION = "Start";
|
||||
|
||||
private static final String DS_TYPE = "type";
|
||||
|
||||
private static final String SW_MODULES = "swModules";
|
||||
|
||||
private static final String IS_REQUIRED_MIGRATION_STEP = "isRequiredMigrationStep";
|
||||
|
||||
private static final String ROLLOUT_RENDERER_DATA = "rolloutRendererData";
|
||||
|
||||
@Autowired
|
||||
private transient RolloutManagement rolloutManagement;
|
||||
@@ -95,7 +110,10 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
|
||||
private transient Map<RolloutStatus, StatusFontIcon> statusIconMap = new EnumMap<>(RolloutStatus.class);
|
||||
|
||||
|
||||
/**
|
||||
* Handles the RolloutEvent to refresh Grid.
|
||||
*
|
||||
*/
|
||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||
void onEvent(final RolloutEvent event) {
|
||||
switch (event) {
|
||||
@@ -132,10 +150,16 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rollout.getStatus());
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setValue(totalTargetCountStatus);
|
||||
final Long groupCount = (Long) item.getItemProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).getValue();
|
||||
if (rollout.getRolloutGroups() != null && groupCount != rollout.getRolloutGroups().size()) {
|
||||
final int groupsCreated = rollout.getRolloutGroupsCreated();
|
||||
if (groupsCreated != 0) {
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setValue(Long.valueOf(groupsCreated));
|
||||
} else if (rollout.getRolloutGroups() != null && groupCount != rollout.getRolloutGroups().size()) {
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS)
|
||||
.setValue(Long.valueOf(rollout.getRolloutGroups().size()));
|
||||
}
|
||||
item.getItemProperty(ROLLOUT_RENDERER_DATA)
|
||||
.setValue(new RolloutRendererData(rollout.getName(), rollout.getStatus().toString()));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,7 +173,11 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
protected void addContainerProperties() {
|
||||
final LazyQueryContainer rolloutGridContainer = (LazyQueryContainer) getContainerDataSource();
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, "", false, false);
|
||||
rolloutGridContainer.addContainerProperty(DS_TYPE, String.class, null, false, false);
|
||||
rolloutGridContainer.addContainerProperty(SW_MODULES, Set.class, null, false, false);
|
||||
rolloutGridContainer.addContainerProperty(ROLLOUT_RENDERER_DATA, RolloutRendererData.class, null, false, false);
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, null, false, false);
|
||||
rolloutGridContainer.addContainerProperty(IS_REQUIRED_MIGRATION_STEP, boolean.class, null, false, false);
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_STATUS, RolloutStatus.class, null, false,
|
||||
false);
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_DIST_NAME_VERSION, String.class, null, false,
|
||||
@@ -163,7 +191,7 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
false);
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_MODIFIED_BY, String.class, null, false,
|
||||
false);
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS, Integer.class, 0, false,
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS, Long.class, 0, false,
|
||||
false);
|
||||
rolloutGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS, String.class, "0", false,
|
||||
false);
|
||||
@@ -177,8 +205,9 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
|
||||
@Override
|
||||
protected void setColumnExpandRatio() {
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME).setMinimumWidth(40);
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME).setMaximumWidth(150);
|
||||
|
||||
getColumn(ROLLOUT_RENDERER_DATA).setMinimumWidth(40);
|
||||
getColumn(ROLLOUT_RENDERER_DATA).setMaximumWidth(150);
|
||||
|
||||
getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setMinimumWidth(40);
|
||||
getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setMaximumWidth(150);
|
||||
@@ -202,7 +231,10 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
|
||||
@Override
|
||||
protected void setColumnHeaderNames() {
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME).setHeaderCaption(i18n.get("header.name"));
|
||||
getColumn(ROLLOUT_RENDERER_DATA).setHeaderCaption(i18n.get("header.name"));
|
||||
getColumn(DS_TYPE).setHeaderCaption("Type");
|
||||
getColumn(SW_MODULES).setHeaderCaption("swModules");
|
||||
getColumn(IS_REQUIRED_MIGRATION_STEP).setHeaderCaption("IsRequiredMigrationStep");
|
||||
getColumn(SPUILabelDefinitions.VAR_DIST_NAME_VERSION).setHeaderCaption(i18n.get("header.distributionset"));
|
||||
getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setHeaderCaption(i18n.get("header.numberofgroups"));
|
||||
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setHeaderCaption(i18n.get("header.total.targets"));
|
||||
@@ -225,8 +257,11 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
@Override
|
||||
protected void setColumnProperties() {
|
||||
final List<Object> columnList = new ArrayList<>();
|
||||
columnList.add(SPUILabelDefinitions.VAR_NAME);
|
||||
columnList.add(ROLLOUT_RENDERER_DATA);
|
||||
columnList.add(SPUILabelDefinitions.VAR_DIST_NAME_VERSION);
|
||||
columnList.add(DS_TYPE);
|
||||
columnList.add(SW_MODULES);
|
||||
columnList.add(IS_REQUIRED_MIGRATION_STEP);
|
||||
columnList.add(SPUILabelDefinitions.VAR_STATUS);
|
||||
columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS);
|
||||
columnList.add(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS);
|
||||
@@ -245,11 +280,15 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
@Override
|
||||
protected void setHiddenColumns() {
|
||||
final List<Object> columnsToBeHidden = new ArrayList<>();
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_NAME);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_DATE);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_USER);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_MODIFIED_DATE);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_MODIFIED_BY);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_DESC);
|
||||
columnsToBeHidden.add(IS_REQUIRED_MIGRATION_STEP);
|
||||
columnsToBeHidden.add(DS_TYPE);
|
||||
columnsToBeHidden.add(SW_MODULES);
|
||||
for (final Object propertyId : columnsToBeHidden) {
|
||||
getColumn(propertyId).setHidden(true);
|
||||
}
|
||||
@@ -263,6 +302,8 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
|
||||
@Override
|
||||
protected void addColumnRenderes() {
|
||||
getColumn(SPUILabelDefinitions.VAR_NUMBER_OF_GROUPS).setRenderer(new HtmlRenderer(),
|
||||
new TotalTargetGroupsConverter());
|
||||
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setRenderer(new HtmlRenderer(),
|
||||
new TotalTargetCountStatusConverter());
|
||||
|
||||
@@ -270,7 +311,11 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
getColumn(SPUILabelDefinitions.VAR_STATUS).setRenderer(new HtmlLabelRenderer(), new RolloutStatusConverter());
|
||||
|
||||
getColumn(SPUILabelDefinitions.ACTION).setRenderer(new HtmlButtonRenderer(event -> onClickOfActionBtn(event)));
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME).setRenderer(new LinkRenderer(event -> onClickOfRolloutName(event)));
|
||||
|
||||
final RolloutRenderer customObjectRenderer = new RolloutRenderer(RolloutRendererData.class);
|
||||
customObjectRenderer.addClickListener(event -> onClickOfRolloutName(event));
|
||||
getColumn(ROLLOUT_RENDERER_DATA).setRenderer(customObjectRenderer);
|
||||
|
||||
}
|
||||
|
||||
private void createRolloutStatusToFontMap() {
|
||||
@@ -403,6 +448,9 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
((LazyQueryContainer) getContainerDataSource()).refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generator to generate fontIcon by String.
|
||||
*/
|
||||
public final class FontIconGenerator extends PropertyValueGenerator<String> {
|
||||
|
||||
private static final long serialVersionUID = 2544026030795375748L;
|
||||
@@ -428,15 +476,54 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
return cell.getProperty().getValue().toString().toLowerCase();
|
||||
} else if (SPUILabelDefinitions.ACTION.equals(cell.getPropertyId())) {
|
||||
return SPUILabelDefinitions.ACTION.toLowerCase();
|
||||
} else if (SPUILabelDefinitions.VAR_NAME.equals(cell.getPropertyId())) {
|
||||
return cell.getProperty().getValue().toString();
|
||||
} else if (ROLLOUT_RENDERER_DATA.equals(cell.getPropertyId())) {
|
||||
return ((RolloutRendererData) cell.getProperty().getValue()).getName();
|
||||
} else if (SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS.equals(cell.getPropertyId())) {
|
||||
return DistributionBarHelper
|
||||
.getTooltip(((TotalTargetCountStatus) cell.getValue()).getStatusTotalCountMap());
|
||||
} else if (SPUILabelDefinitions.VAR_DIST_NAME_VERSION.equals(cell.getPropertyId())) {
|
||||
return getDSDetails(cell.getItem());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getDSDetails(final Item rolloutItem) {
|
||||
final StringBuilder swModuleNames = new StringBuilder();
|
||||
final StringBuilder swModuleVendors = new StringBuilder();
|
||||
final Set<SoftwareModule> swModules = (Set<SoftwareModule>) rolloutItem.getItemProperty(SW_MODULES).getValue();
|
||||
swModules.forEach(swModule -> {
|
||||
swModuleNames.append(swModule.getName());
|
||||
swModuleNames.append(" , ");
|
||||
swModuleVendors.append(swModule.getVendor());
|
||||
swModuleVendors.append(" , ");
|
||||
});
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append(HTML_UL_OPEN_TAG);
|
||||
stringBuilder.append(HTML_LI_OPEN_TAG);
|
||||
stringBuilder.append(" DistributionSet Description : ")
|
||||
.append((String) rolloutItem.getItemProperty(SPUILabelDefinitions.VAR_DESC).getValue());
|
||||
stringBuilder.append(HTML_LI_CLOSE_TAG);
|
||||
stringBuilder.append(HTML_LI_OPEN_TAG);
|
||||
stringBuilder.append(" DistributionSet Type : ")
|
||||
.append((String) rolloutItem.getItemProperty(DS_TYPE).getValue());
|
||||
stringBuilder.append(HTML_LI_CLOSE_TAG);
|
||||
stringBuilder.append(HTML_LI_OPEN_TAG);
|
||||
stringBuilder.append("Required Migration step : ")
|
||||
.append((boolean) rolloutItem.getItemProperty(IS_REQUIRED_MIGRATION_STEP).getValue() ? "Yes" : "No");
|
||||
stringBuilder.append(HTML_LI_CLOSE_TAG);
|
||||
|
||||
stringBuilder.append(HTML_LI_OPEN_TAG);
|
||||
stringBuilder.append("SoftWare Modules : ").append(swModuleNames.toString());
|
||||
stringBuilder.append(HTML_LI_CLOSE_TAG);
|
||||
|
||||
stringBuilder.append(HTML_LI_OPEN_TAG);
|
||||
stringBuilder.append("Vendor(s) : ").append(swModuleVendors.toString());
|
||||
stringBuilder.append(HTML_LI_CLOSE_TAG);
|
||||
|
||||
stringBuilder.append(HTML_UL_CLOSE_TAG);
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
enum ACTION {
|
||||
PAUSE, RESUME, START, UPDATE
|
||||
}
|
||||
@@ -568,4 +655,39 @@ public class RolloutListGrid extends AbstractGrid {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converter to convert 0 to empty, if total target groups is zero.
|
||||
*
|
||||
*/
|
||||
class TotalTargetGroupsConverter implements Converter<String, Long> {
|
||||
|
||||
private static final long serialVersionUID = 6589305227035220369L;
|
||||
|
||||
@Override
|
||||
public Long convertToModel(final String value, final Class<? extends Long> targetType, final Locale locale)
|
||||
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToPresentation(final Long value, final Class<? extends String> targetType,
|
||||
final Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||
if (value == 0) {
|
||||
return "";
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Long> getModelType() {
|
||||
return Long.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<String> getPresentationType() {
|
||||
return String.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,200 +9,211 @@
|
||||
package org.eclipse.hawkbit.ui.rollout.rolloutgroup;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
|
||||
/**
|
||||
* Proxy rollout group with suctome properties.
|
||||
* Proxy rollout group with renderer properties.
|
||||
*
|
||||
*/
|
||||
public class ProxyRolloutGroup extends RolloutGroup {
|
||||
|
||||
private static final long serialVersionUID = -2745056813306692356L;
|
||||
private static final long serialVersionUID = -2745056813306692356L;
|
||||
|
||||
private String createdDate;
|
||||
private String createdDate;
|
||||
|
||||
private String modifiedDate;
|
||||
private String modifiedDate;
|
||||
|
||||
private String finishedPercentage;
|
||||
private String finishedPercentage;
|
||||
|
||||
private Long runningTargetsCount;
|
||||
private Long runningTargetsCount;
|
||||
|
||||
private Long scheduledTargetsCount;
|
||||
private Long scheduledTargetsCount;
|
||||
|
||||
private Long cancelledTargetsCount;
|
||||
private Long cancelledTargetsCount;
|
||||
|
||||
private Long errorTargetsCount;
|
||||
private Long errorTargetsCount;
|
||||
|
||||
private Long finishedTargetsCount;
|
||||
private Long finishedTargetsCount;
|
||||
|
||||
private Long notStartedTargetsCount;
|
||||
private Long notStartedTargetsCount;
|
||||
|
||||
private Boolean isActionRecieved = Boolean.FALSE;
|
||||
private Boolean isActionRecieved = Boolean.FALSE;
|
||||
|
||||
private String totalTargetsCount;
|
||||
private String totalTargetsCount;
|
||||
|
||||
/**
|
||||
* @return the createdDate
|
||||
*/
|
||||
public String getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
private RolloutRendererData rolloutRendererData;
|
||||
|
||||
/**
|
||||
* @param createdDate
|
||||
* the createdDate to set
|
||||
*/
|
||||
public void setCreatedDate(final String createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
public RolloutRendererData getRolloutRendererData() {
|
||||
return rolloutRendererData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the modifiedDate
|
||||
*/
|
||||
public String getModifiedDate() {
|
||||
return modifiedDate;
|
||||
}
|
||||
public void setRolloutRendererData(RolloutRendererData rendererData) {
|
||||
this.rolloutRendererData = rendererData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modifiedDate
|
||||
* the modifiedDate to set
|
||||
*/
|
||||
public void setModifiedDate(final String modifiedDate) {
|
||||
this.modifiedDate = modifiedDate;
|
||||
}
|
||||
/**
|
||||
* @return the createdDate
|
||||
*/
|
||||
public String getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the finishedPercentage
|
||||
*/
|
||||
public String getFinishedPercentage() {
|
||||
return finishedPercentage;
|
||||
}
|
||||
/**
|
||||
* @param createdDate
|
||||
* the createdDate to set
|
||||
*/
|
||||
public void setCreatedDate(final String createdDate) {
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param finishedPercentage
|
||||
* the finishedPercentage to set
|
||||
*/
|
||||
public void setFinishedPercentage(final String finishedPercentage) {
|
||||
this.finishedPercentage = finishedPercentage;
|
||||
}
|
||||
/**
|
||||
* @return the modifiedDate
|
||||
*/
|
||||
public String getModifiedDate() {
|
||||
return modifiedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the runningTargetsCount
|
||||
*/
|
||||
public Long getRunningTargetsCount() {
|
||||
return runningTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @param modifiedDate
|
||||
* the modifiedDate to set
|
||||
*/
|
||||
public void setModifiedDate(final String modifiedDate) {
|
||||
this.modifiedDate = modifiedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param runningTargetsCount
|
||||
* the runningTargetsCount to set
|
||||
*/
|
||||
public void setRunningTargetsCount(final Long runningTargetsCount) {
|
||||
this.runningTargetsCount = runningTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @return the finishedPercentage
|
||||
*/
|
||||
public String getFinishedPercentage() {
|
||||
return finishedPercentage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scheduledTargetsCount
|
||||
*/
|
||||
public Long getScheduledTargetsCount() {
|
||||
return scheduledTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @param finishedPercentage
|
||||
* the finishedPercentage to set
|
||||
*/
|
||||
public void setFinishedPercentage(final String finishedPercentage) {
|
||||
this.finishedPercentage = finishedPercentage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scheduledTargetsCount
|
||||
* the scheduledTargetsCount to set
|
||||
*/
|
||||
public void setScheduledTargetsCount(final Long scheduledTargetsCount) {
|
||||
this.scheduledTargetsCount = scheduledTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @return the runningTargetsCount
|
||||
*/
|
||||
public Long getRunningTargetsCount() {
|
||||
return runningTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the cancelledTargetsCount
|
||||
*/
|
||||
public Long getCancelledTargetsCount() {
|
||||
return cancelledTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @param runningTargetsCount
|
||||
* the runningTargetsCount to set
|
||||
*/
|
||||
public void setRunningTargetsCount(final Long runningTargetsCount) {
|
||||
this.runningTargetsCount = runningTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cancelledTargetsCount
|
||||
* the cancelledTargetsCount to set
|
||||
*/
|
||||
public void setCancelledTargetsCount(final Long cancelledTargetsCount) {
|
||||
this.cancelledTargetsCount = cancelledTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @return the scheduledTargetsCount
|
||||
*/
|
||||
public Long getScheduledTargetsCount() {
|
||||
return scheduledTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the errorTargetsCount
|
||||
*/
|
||||
public Long getErrorTargetsCount() {
|
||||
return errorTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @param scheduledTargetsCount
|
||||
* the scheduledTargetsCount to set
|
||||
*/
|
||||
public void setScheduledTargetsCount(final Long scheduledTargetsCount) {
|
||||
this.scheduledTargetsCount = scheduledTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorTargetsCount
|
||||
* the errorTargetsCount to set
|
||||
*/
|
||||
public void setErrorTargetsCount(final Long errorTargetsCount) {
|
||||
this.errorTargetsCount = errorTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @return the cancelledTargetsCount
|
||||
*/
|
||||
public Long getCancelledTargetsCount() {
|
||||
return cancelledTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the finishedTargetsCount
|
||||
*/
|
||||
public Long getFinishedTargetsCount() {
|
||||
return finishedTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @param cancelledTargetsCount
|
||||
* the cancelledTargetsCount to set
|
||||
*/
|
||||
public void setCancelledTargetsCount(final Long cancelledTargetsCount) {
|
||||
this.cancelledTargetsCount = cancelledTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param finishedTargetsCount
|
||||
* the finishedTargetsCount to set
|
||||
*/
|
||||
public void setFinishedTargetsCount(final Long finishedTargetsCount) {
|
||||
this.finishedTargetsCount = finishedTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @return the errorTargetsCount
|
||||
*/
|
||||
public Long getErrorTargetsCount() {
|
||||
return errorTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the notStartedTargetsCount
|
||||
*/
|
||||
public Long getNotStartedTargetsCount() {
|
||||
return notStartedTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @param errorTargetsCount
|
||||
* the errorTargetsCount to set
|
||||
*/
|
||||
public void setErrorTargetsCount(final Long errorTargetsCount) {
|
||||
this.errorTargetsCount = errorTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param notStartedTargetsCount
|
||||
* the notStartedTargetsCount to set
|
||||
*/
|
||||
public void setNotStartedTargetsCount(final Long notStartedTargetsCount) {
|
||||
this.notStartedTargetsCount = notStartedTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @return the finishedTargetsCount
|
||||
*/
|
||||
public Long getFinishedTargetsCount() {
|
||||
return finishedTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the isActionRecieved
|
||||
*/
|
||||
public Boolean getIsActionRecieved() {
|
||||
return isActionRecieved;
|
||||
}
|
||||
/**
|
||||
* @param finishedTargetsCount
|
||||
* the finishedTargetsCount to set
|
||||
*/
|
||||
public void setFinishedTargetsCount(final Long finishedTargetsCount) {
|
||||
this.finishedTargetsCount = finishedTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isActionRecieved
|
||||
* the isActionRecieved to set
|
||||
*/
|
||||
public void setIsActionRecieved(final Boolean isActionRecieved) {
|
||||
this.isActionRecieved = isActionRecieved;
|
||||
}
|
||||
/**
|
||||
* @return the notStartedTargetsCount
|
||||
*/
|
||||
public Long getNotStartedTargetsCount() {
|
||||
return notStartedTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the totalTargetsCount
|
||||
*/
|
||||
public String getTotalTargetsCount() {
|
||||
return totalTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @param notStartedTargetsCount
|
||||
* the notStartedTargetsCount to set
|
||||
*/
|
||||
public void setNotStartedTargetsCount(final Long notStartedTargetsCount) {
|
||||
this.notStartedTargetsCount = notStartedTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param totalTargetsCount
|
||||
* the totalTargetsCount to set
|
||||
*/
|
||||
public void setTotalTargetsCount(final String totalTargetsCount) {
|
||||
this.totalTargetsCount = totalTargetsCount;
|
||||
}
|
||||
/**
|
||||
* @return the isActionRecieved
|
||||
*/
|
||||
public Boolean getIsActionRecieved() {
|
||||
return isActionRecieved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isActionRecieved
|
||||
* the isActionRecieved to set
|
||||
*/
|
||||
public void setIsActionRecieved(final Boolean isActionRecieved) {
|
||||
this.isActionRecieved = isActionRecieved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the totalTargetsCount
|
||||
*/
|
||||
public String getTotalTargetsCount() {
|
||||
return totalTargetsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param totalTargetsCount
|
||||
* the totalTargetsCount to set
|
||||
*/
|
||||
public void setTotalTargetsCount(final String totalTargetsCount) {
|
||||
this.totalTargetsCount = totalTargetsCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import java.util.Map;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||
@@ -110,8 +112,8 @@ public class RolloutGroupBeanQuery extends AbstractBeanQuery<ProxyRolloutGroup>
|
||||
proxyRolloutGroup.setDescription(rolloutGroup.getDescription());
|
||||
proxyRolloutGroup.setCreatedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getCreatedAt()));
|
||||
proxyRolloutGroup.setModifiedDate(SPDateTimeUtil.getFormattedDate(rolloutGroup.getLastModifiedAt()));
|
||||
proxyRolloutGroup.setCreatedBy(HawkbitCommonUtil.getIMUser(rolloutGroup.getCreatedBy()));
|
||||
proxyRolloutGroup.setLastModifiedBy(HawkbitCommonUtil.getIMUser(rolloutGroup.getLastModifiedBy()));
|
||||
proxyRolloutGroup.setCreatedBy(UserDetailsFormatter.loadAndFormatCreatedBy(rolloutGroup));
|
||||
proxyRolloutGroup.setLastModifiedBy(UserDetailsFormatter.loadAndFormatLastModifiedBy(rolloutGroup));
|
||||
proxyRolloutGroup.setId(rolloutGroup.getId());
|
||||
proxyRolloutGroup.setStatus(rolloutGroup.getStatus());
|
||||
proxyRolloutGroup.setErrorAction(rolloutGroup.getErrorAction());
|
||||
@@ -122,6 +124,8 @@ public class RolloutGroupBeanQuery extends AbstractBeanQuery<ProxyRolloutGroup>
|
||||
proxyRolloutGroup.setSuccessConditionExp(rolloutGroup.getSuccessConditionExp());
|
||||
proxyRolloutGroup.setFinishedPercentage(calculateFinishedPercentage(rolloutGroup));
|
||||
|
||||
proxyRolloutGroup.setRolloutRendererData(new RolloutRendererData(rolloutGroup.getName(), null));
|
||||
|
||||
proxyRolloutGroup.setTotalTargetsCount(String.valueOf(rolloutGroup.getTotalTargets()));
|
||||
proxyRolloutGroup.setTotalTargetCountStatus(rolloutGroup.getTotalTargetCountStatus());
|
||||
|
||||
|
||||
@@ -17,13 +17,15 @@ import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.RolloutGroupChangeEvent;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||
import org.eclipse.hawkbit.ui.common.grid.AbstractGrid;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRendererData;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlLabelRenderer;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.LinkRenderer;
|
||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer;
|
||||
import org.eclipse.hawkbit.ui.rollout.DistributionBarHelper;
|
||||
import org.eclipse.hawkbit.ui.rollout.StatusFontIcon;
|
||||
import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent;
|
||||
@@ -59,9 +61,14 @@ import com.vaadin.ui.renderers.HtmlRenderer;
|
||||
public class RolloutGroupListGrid extends AbstractGrid {
|
||||
private static final long serialVersionUID = 4060904914954370524L;
|
||||
|
||||
private static final String ROLLOUT_RENDERER_DATA = "rolloutRendererData";
|
||||
|
||||
@Autowired
|
||||
private transient RolloutGroupManagement rolloutGroupManagement;
|
||||
|
||||
@Autowired
|
||||
private transient RolloutManagement rolloutManagement;
|
||||
|
||||
@Autowired
|
||||
private transient RolloutUIState rolloutUIState;
|
||||
|
||||
@@ -103,6 +110,13 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_STATUS).setValue(rolloutGroup.getStatus());
|
||||
item.getItemProperty(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS)
|
||||
.setValue(rolloutGroup.getTotalTargetCountStatus());
|
||||
item.getItemProperty(SPUILabelDefinitions.ROLLOUT_GROUP_INSTALLED_PERCENTAGE)
|
||||
.setValue(calculateFinishedPercentage(rolloutGroup));
|
||||
}
|
||||
|
||||
private String calculateFinishedPercentage(final RolloutGroup rolloutGroup) {
|
||||
return HawkbitCommonUtil.formattingFinishedPercentage(rolloutGroup,
|
||||
rolloutManagement.getFinishedPercentForRunningGroup(rolloutGroup.getRollout().getId(), rolloutGroup));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,6 +130,9 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
protected void addContainerProperties() {
|
||||
final LazyQueryContainer rolloutGroupGridContainer = (LazyQueryContainer) getContainerDataSource();
|
||||
rolloutGroupGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, "", false, false);
|
||||
|
||||
rolloutGroupGridContainer.addContainerProperty(ROLLOUT_RENDERER_DATA, RolloutRendererData.class, null, false,
|
||||
false);
|
||||
rolloutGroupGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_DESC, String.class, null, false, false);
|
||||
rolloutGroupGridContainer.addContainerProperty(SPUILabelDefinitions.VAR_STATUS, RolloutGroupStatus.class, null,
|
||||
false, false);
|
||||
@@ -145,8 +162,8 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
|
||||
@Override
|
||||
protected void setColumnExpandRatio() {
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME).setMinimumWidth(40);
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME).setMaximumWidth(200);
|
||||
getColumn(ROLLOUT_RENDERER_DATA).setMinimumWidth(40);
|
||||
getColumn(ROLLOUT_RENDERER_DATA).setMaximumWidth(200);
|
||||
|
||||
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setMinimumWidth(40);
|
||||
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS).setMaximumWidth(100);
|
||||
@@ -170,7 +187,7 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
|
||||
@Override
|
||||
protected void setColumnHeaderNames() {
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME).setHeaderCaption(i18n.get("header.name"));
|
||||
getColumn(ROLLOUT_RENDERER_DATA).setHeaderCaption(i18n.get("header.name"));
|
||||
getColumn(SPUILabelDefinitions.VAR_STATUS).setHeaderCaption(i18n.get("header.status"));
|
||||
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS)
|
||||
.setHeaderCaption(i18n.get("header.detail.status"));
|
||||
@@ -196,7 +213,7 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
@Override
|
||||
protected void setColumnProperties() {
|
||||
final List<Object> columnList = new ArrayList<>();
|
||||
columnList.add(SPUILabelDefinitions.VAR_NAME);
|
||||
columnList.add(ROLLOUT_RENDERER_DATA);
|
||||
columnList.add(SPUILabelDefinitions.VAR_STATUS);
|
||||
columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS);
|
||||
columnList.add(SPUILabelDefinitions.VAR_TOTAL_TARGETS);
|
||||
@@ -221,14 +238,15 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
getColumn(SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS).setRenderer(new HtmlRenderer(),
|
||||
new TotalTargetCountStatusConverter());
|
||||
if (permissionChecker.hasRolloutTargetsReadPermission()) {
|
||||
getColumn(SPUILabelDefinitions.VAR_NAME)
|
||||
.setRenderer(new LinkRenderer(event -> onClickOfRolloutGroupName(event)));
|
||||
getColumn(ROLLOUT_RENDERER_DATA)
|
||||
.setRenderer(new RolloutRenderer(event -> onClickOfRolloutGroupName(event)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setHiddenColumns() {
|
||||
final List<Object> columnsToBeHidden = new ArrayList<>();
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_NAME);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_DATE);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_CREATED_USER);
|
||||
columnsToBeHidden.add(SPUILabelDefinitions.VAR_MODIFIED_DATE);
|
||||
@@ -268,8 +286,8 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
return cell.getProperty().getValue().toString().toLowerCase();
|
||||
} else if (SPUILabelDefinitions.ACTION.equals(cell.getPropertyId())) {
|
||||
return SPUILabelDefinitions.ACTION.toLowerCase();
|
||||
} else if (SPUILabelDefinitions.VAR_NAME.equals(cell.getPropertyId())) {
|
||||
return cell.getProperty().getValue().toString();
|
||||
} else if (ROLLOUT_RENDERER_DATA.equals(cell.getPropertyId())) {
|
||||
return ((RolloutRendererData) cell.getProperty().getValue()).getName();
|
||||
} else if (SPUILabelDefinitions.VAR_TOTAL_TARGETS_COUNT_STATUS.equals(cell.getPropertyId())) {
|
||||
return DistributionBarHelper
|
||||
.getTooltip(((TotalTargetCountStatus) cell.getValue()).getStatusTotalCountMap());
|
||||
@@ -306,14 +324,14 @@ public class RolloutGroupListGrid extends AbstractGrid {
|
||||
@Override
|
||||
public TotalTargetCountStatus convertToModel(final String value,
|
||||
final Class<? extends TotalTargetCountStatus> targetType, final Locale locale)
|
||||
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToPresentation(final TotalTargetCountStatus value,
|
||||
final Class<? extends String> targetType, final Locale locale)
|
||||
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||
throws com.vaadin.data.util.converter.Converter.ConversionException {
|
||||
return DistributionBarHelper.getDistributionBarAsHTMLString(value.getStatusTotalCountMap());
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +161,7 @@ public class RolloutGroupsListHeader extends AbstractGridHeader {
|
||||
final HorizontalLayout headerCaptionLayout = new HorizontalLayout();
|
||||
headerCaptionLayout.addComponent(rolloutsListViewLink);
|
||||
headerCaptionLayout.addComponent(new Label(">"));
|
||||
headerCaption.addStyleName("breadcrumbPaddingLeft");
|
||||
headerCaptionLayout.addComponent(headerCaption);
|
||||
|
||||
return headerCaptionLayout;
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetWithActionStatus;
|
||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||
import org.eclipse.hawkbit.ui.components.ProxyTarget;
|
||||
import org.eclipse.hawkbit.ui.rollout.state.RolloutUIState;
|
||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||
@@ -105,8 +106,8 @@ public class RolloutGroupTargetsBeanQuery extends AbstractBeanQuery<ProxyTarget>
|
||||
prxyTarget.setLastModifiedDate(SPDateTimeUtil.getFormattedDate(targ.getLastModifiedAt()));
|
||||
prxyTarget.setCreatedDate(SPDateTimeUtil.getFormattedDate(targ.getCreatedAt()));
|
||||
prxyTarget.setCreatedAt(targ.getCreatedAt());
|
||||
prxyTarget.setCreatedByUser(HawkbitCommonUtil.getIMUser(targ.getCreatedBy()));
|
||||
prxyTarget.setModifiedByUser(HawkbitCommonUtil.getIMUser(targ.getLastModifiedBy()));
|
||||
prxyTarget.setCreatedByUser(UserDetailsFormatter.loadAndFormatCreatedBy(targ));
|
||||
prxyTarget.setModifiedByUser(UserDetailsFormatter.loadAndFormatLastModifiedBy(targ));
|
||||
if (targetWithActionStatus.getStatus() != null) {
|
||||
prxyTarget.setStatus(targetWithActionStatus.getStatus());
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user