Merge branch 'eclipse/master' into
fix_unhandled_ConstraintViolationException Conflicts: hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
@@ -24,6 +24,12 @@ The simulator has user authentication enabled in **cloud profile**. Default cred
|
|||||||
|
|
||||||
This can be configured/disabled by spring boot properties
|
This can be configured/disabled by spring boot properties
|
||||||
|
|
||||||
|
## hawkBit APIs
|
||||||
|
|
||||||
|
The simulator supports `DDI` as well as the `DMF` integration APIs.
|
||||||
|
In case there is no AMQP message broker (like rabbitMQ) running, you can disable the AMQP support for the device simulator, so the simulator is not trying to connect to an amqp message broker.
|
||||||
|
Configuration property `hawkbit.device.simulator.amqp.enabled=true`
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Graphical User Interface
|
### Graphical User Interface
|
||||||
|
|||||||
@@ -17,6 +17,4 @@ applications:
|
|||||||
services:
|
services:
|
||||||
- dmf-rabbit
|
- dmf-rabbit
|
||||||
env:
|
env:
|
||||||
SPRING_PROFILES_ACTIVE: cloud,amqp
|
SPRING_PROFILES_ACTIVE: cloud
|
||||||
CF_STAGING_TIMEOUT: 15
|
|
||||||
CF_STARTUP_TIMEOUT: 15
|
|
||||||
|
|||||||
@@ -8,9 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator;
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
|
import static java.util.concurrent.Executors.newScheduledThreadPool;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.security.DigestOutputStream;
|
import java.security.DigestOutputStream;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
@@ -20,7 +23,6 @@ import java.security.SecureRandom;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -56,9 +58,10 @@ import com.google.common.io.ByteStreams;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class DeviceSimulatorUpdater {
|
public class DeviceSimulatorUpdater {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class);
|
||||||
|
|
||||||
private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(8);
|
private static final ScheduledExecutorService threadPool = newScheduledThreadPool(8);
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SpSenderService spSenderService;
|
private SpSenderService spSenderService;
|
||||||
@@ -118,14 +121,9 @@ public class DeviceSimulatorUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class DeviceSimulatorUpdateThread implements Runnable {
|
private static final class DeviceSimulatorUpdateThread implements Runnable {
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final String BUT_GOT_LOG_MESSAGE = " but got: ";
|
private static final String BUT_GOT_LOG_MESSAGE = " but got: ";
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final String DOWNLOAD_LOG_MESSAGE = "Download ";
|
private static final String DOWNLOAD_LOG_MESSAGE = "Download ";
|
||||||
|
|
||||||
private static final int MINIMUM_TOKENLENGTH_FOR_HINT = 6;
|
private static final int MINIMUM_TOKENLENGTH_FOR_HINT = 6;
|
||||||
@@ -279,13 +277,17 @@ public class DeviceSimulatorUpdater {
|
|||||||
|
|
||||||
private static long getOverallRead(final CloseableHttpResponse response, final MessageDigest md)
|
private static long getOverallRead(final CloseableHttpResponse response, final MessageDigest md)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
||||||
long overallread;
|
long overallread;
|
||||||
try (final BufferedOutputStream bdos = new BufferedOutputStream(
|
|
||||||
new DigestOutputStream(ByteStreams.nullOutputStream(), md))) {
|
try (final OutputStream os = ByteStreams.nullOutputStream();
|
||||||
|
final BufferedOutputStream bos = new BufferedOutputStream(new DigestOutputStream(os, md))) {
|
||||||
|
|
||||||
try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) {
|
try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) {
|
||||||
overallread = ByteStreams.copy(bis, bdos);
|
overallread = ByteStreams.copy(bis, bos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return overallread;
|
return overallread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public class SimulatedDeviceFactory {
|
|||||||
final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) {
|
final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) {
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case DMF_AMQP:
|
case DMF_AMQP:
|
||||||
|
spSenderService.createOrUpdateThing(tenant, id);
|
||||||
return new DMFSimulatedDevice(id, tenant, spSenderService, pollDelaySec);
|
return new DMFSimulatedDevice(id, tenant, spSenderService, pollDelaySec);
|
||||||
case DDI_HTTP:
|
case DDI_HTTP:
|
||||||
final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger())
|
final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger())
|
||||||
|
|||||||
@@ -8,11 +8,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator;
|
package org.eclipse.hawkbit.simulator;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -21,22 +23,19 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* REST endpoint for controlling the device simulator.
|
* REST endpoint for controlling the device simulator.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
public class SimulationController {
|
public class SimulationController {
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SpSenderService spSenderService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceSimulatorRepository repository;
|
private DeviceSimulatorRepository repository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SimulatedDeviceFactory deviceFactory;
|
private SimulatedDeviceFactory deviceFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmqpProperties amqpProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The start resource to start a device creation.
|
* The start resource to start a device creation.
|
||||||
*
|
*
|
||||||
@@ -82,6 +81,12 @@ public class SimulationController {
|
|||||||
return ResponseEntity.badRequest().body("query param api only allows value of 'dmf' or 'ddi'");
|
return ResponseEntity.badRequest().body("query param api only allows value of 'dmf' or 'ddi'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (protocol == Protocol.DMF_AMQP && isDmfDisabled()) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body("The AMQP interface has been disabled, to use DMF protocol you need to enable the AMQP interface via '"
|
||||||
|
+ CONFIGURATION_PREFIX + ".enabled=true'");
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < amount; i++) {
|
for (int i = 0; i < amount; i++) {
|
||||||
final String deviceId = name + i;
|
final String deviceId = name + i;
|
||||||
repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint),
|
repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint),
|
||||||
@@ -90,4 +95,8 @@ public class SimulationController {
|
|||||||
|
|
||||||
return ResponseEntity.ok("Updated " + amount + " DMF connected targets!");
|
return ResponseEntity.ok("Updated " + amount + " DMF connected targets!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDmfDisabled() {
|
||||||
|
return !amqpProperties.isEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.simulator;
|
|||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -32,24 +32,27 @@ public class SimulatorStartup implements ApplicationListener<ContextRefreshedEve
|
|||||||
@Autowired
|
@Autowired
|
||||||
private SimulationProperties simulationProperties;
|
private SimulationProperties simulationProperties;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SpSenderService spSenderService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DeviceSimulatorRepository repository;
|
private DeviceSimulatorRepository repository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private SimulatedDeviceFactory deviceFactory;
|
private SimulatedDeviceFactory deviceFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmqpProperties amqpProperties;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(final ContextRefreshedEvent event) {
|
public void onApplicationEvent(final ContextRefreshedEvent event) {
|
||||||
simulationProperties.getAutostarts().forEach(autostart -> {
|
simulationProperties.getAutostarts().forEach(autostart -> {
|
||||||
for (int i = 0; i < autostart.getAmount(); i++) {
|
for (int i = 0; i < autostart.getAmount(); i++) {
|
||||||
final String deviceId = autostart.getName() + i;
|
final String deviceId = autostart.getName() + i;
|
||||||
try {
|
try {
|
||||||
repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(),
|
if (amqpProperties.isEnabled()) {
|
||||||
autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()),
|
repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(),
|
||||||
autostart.getGatewayToken()));
|
autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()),
|
||||||
|
autostart.getGatewayToken()));
|
||||||
|
}
|
||||||
|
|
||||||
} catch (final MalformedURLException e) {
|
} catch (final MalformedURLException e) {
|
||||||
LOGGER.error("Creation of simulated device at startup failed.", e);
|
LOGGER.error("Creation of simulated device at startup failed.", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator.amqp;
|
package org.eclipse.hawkbit.simulator.amqp;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -27,6 +29,7 @@ import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
|||||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
|
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@@ -39,6 +42,7 @@ import org.springframework.retry.support.RetryTemplate;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableConfigurationProperties(AmqpProperties.class)
|
@EnableConfigurationProperties(AmqpProperties.class)
|
||||||
|
@ConditionalOnProperty(prefix = CONFIGURATION_PREFIX, name = "enabled")
|
||||||
public class AmqpConfiguration {
|
public class AmqpConfiguration {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class);
|
||||||
|
|||||||
@@ -19,6 +19,17 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
||||||
public class AmqpProperties {
|
public class AmqpProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prefix for this configuration.
|
||||||
|
*/
|
||||||
|
public static final String CONFIGURATION_PREFIX = "hawkbit.device.simulator.amqp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the AMQP interface is enabled for the device simulator.
|
||||||
|
*/
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue for receiving DMF messages from update server.
|
* Queue for receiving DMF messages from update server.
|
||||||
*/
|
*/
|
||||||
@@ -84,4 +95,12 @@ public class AmqpProperties {
|
|||||||
public void setDeadLetterTtl(final int deadLetterTtl) {
|
public void setDeadLetterTtl(final int deadLetterTtl) {
|
||||||
this.deadLetterTtl = deadLetterTtl;
|
this.deadLetterTtl = deadLetterTtl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(final boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.simulator.amqp;
|
package org.eclipse.hawkbit.simulator.amqp;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||||
@@ -22,6 +24,7 @@ import org.springframework.amqp.core.MessageProperties;
|
|||||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.messaging.handler.annotation.Header;
|
import org.springframework.messaging.handler.annotation.Header;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -32,6 +35,7 @@ import com.google.common.collect.Lists;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
|
@ConditionalOnProperty(prefix = CONFIGURATION_PREFIX, name = "enabled")
|
||||||
public class SpReceiverService extends ReceiverService {
|
public class SpReceiverService extends ReceiverService {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public class GenerateDialog extends Window {
|
|||||||
private final TextField gatewayTokenTextField;
|
private final TextField gatewayTokenTextField;
|
||||||
private OptionGroup protocolGroup;
|
private OptionGroup protocolGroup;
|
||||||
private Button buttonOk;
|
private Button buttonOk;
|
||||||
|
private final boolean dmfEnabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new pop window for setting the configuration of simulating
|
* Creates a new pop window for setting the configuration of simulating
|
||||||
@@ -60,9 +61,12 @@ public class GenerateDialog extends Window {
|
|||||||
* @param callback
|
* @param callback
|
||||||
* the callback which is called when the dialog has been
|
* the callback which is called when the dialog has been
|
||||||
* successfully confirmed.
|
* successfully confirmed.
|
||||||
|
* @param dmfEnabled
|
||||||
|
* indicates if the AMQP/DMF interface is enabled by
|
||||||
|
* configuration and if the option DMF should be enabled or not
|
||||||
*/
|
*/
|
||||||
public GenerateDialog(final GenerateDialogCallback callback) {
|
public GenerateDialog(final GenerateDialogCallback callback, final boolean dmfEnabled) {
|
||||||
|
this.dmfEnabled = dmfEnabled;
|
||||||
formLayout.setSpacing(true);
|
formLayout.setSpacing(true);
|
||||||
formLayout.setMargin(true);
|
formLayout.setMargin(true);
|
||||||
|
|
||||||
@@ -187,15 +191,19 @@ public class GenerateDialog extends Window {
|
|||||||
this.protocolGroup = new OptionGroup("Simulated Device Protocol");
|
this.protocolGroup = new OptionGroup("Simulated Device Protocol");
|
||||||
protocolGroup.addItem(Protocol.DMF_AMQP);
|
protocolGroup.addItem(Protocol.DMF_AMQP);
|
||||||
protocolGroup.addItem(Protocol.DDI_HTTP);
|
protocolGroup.addItem(Protocol.DDI_HTTP);
|
||||||
|
protocolGroup.select(Protocol.DMF_AMQP);
|
||||||
protocolGroup.setItemCaption(Protocol.DMF_AMQP, "Device Management Federation API (AMQP push)");
|
protocolGroup.setItemCaption(Protocol.DMF_AMQP, "Device Management Federation API (AMQP push)");
|
||||||
protocolGroup.setItemCaption(Protocol.DDI_HTTP, "Direct Device Interface (HTTP poll)");
|
protocolGroup.setItemCaption(Protocol.DDI_HTTP, "Direct Device Interface (HTTP poll)");
|
||||||
protocolGroup.setNullSelectionAllowed(false);
|
protocolGroup.setNullSelectionAllowed(false);
|
||||||
protocolGroup.select(Protocol.DMF_AMQP);
|
|
||||||
protocolGroup.addValueChangeListener(event -> {
|
protocolGroup.addValueChangeListener(event -> {
|
||||||
final boolean directDeviceOptionSelected = event.getProperty().getValue().equals(Protocol.DDI_HTTP);
|
final boolean directDeviceOptionSelected = event.getProperty().getValue().equals(Protocol.DDI_HTTP);
|
||||||
pollUrlTextField.setVisible(directDeviceOptionSelected);
|
pollUrlTextField.setVisible(directDeviceOptionSelected);
|
||||||
gatewayTokenTextField.setVisible(directDeviceOptionSelected);
|
gatewayTokenTextField.setVisible(directDeviceOptionSelected);
|
||||||
});
|
});
|
||||||
|
protocolGroup.setItemEnabled(Protocol.DMF_AMQP, dmfEnabled);
|
||||||
|
if (!dmfEnabled) {
|
||||||
|
protocolGroup.select(Protocol.DDI_HTTP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createOkButton(final GenerateDialogCallback callback) {
|
private void createOkButton(final GenerateDialogCallback callback) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Status;
|
|||||||
import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
|
import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
|
||||||
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
|
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
|
||||||
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||||
|
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties;
|
||||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||||
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
||||||
@@ -90,6 +91,9 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private transient EventBus eventbus;
|
private transient EventBus eventbus;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private transient AmqpProperties amqpProperties;
|
||||||
|
|
||||||
private final Label caption = new Label("DMF/DDI Simulated Devices");
|
private final Label caption = new Label("DMF/DDI Simulated Devices");
|
||||||
private final HorizontalLayout toolbar = new HorizontalLayout();
|
private final HorizontalLayout toolbar = new HorizontalLayout();
|
||||||
private final Grid grid = new Grid();
|
private final Grid grid = new Grid();
|
||||||
@@ -266,9 +270,8 @@ public class SimulatorView extends VerticalLayout implements View {
|
|||||||
final String deviceId = namePrefix + index;
|
final String deviceId = namePrefix + index;
|
||||||
beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId,
|
beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId,
|
||||||
tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken)));
|
tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken)));
|
||||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
|
||||||
}
|
}
|
||||||
}));
|
}, amqpProperties.isEnabled()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProtocolConverter createProtocolConverter() {
|
private ProtocolConverter createProtocolConverter() {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
## Configuration for DMF communication
|
## Configuration for DMF communication
|
||||||
|
hawkbit.device.simulator.amqp.enabled=true
|
||||||
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver
|
hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver
|
||||||
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
|
hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter
|
||||||
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
|
hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ import java.util.Map;
|
|||||||
* An interface for declaring the name of the field described in the database
|
* An interface for declaring the name of the field described in the database
|
||||||
* which is used as string representation of the field, e.g. for sorting the
|
* which is used as string representation of the field, e.g. for sorting the
|
||||||
* fields over REST.
|
* fields over REST.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
public interface FieldNameProvider {
|
public interface FieldNameProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Separator for the sub attributes
|
* Separator for the sub attributes
|
||||||
*/
|
*/
|
||||||
@@ -32,64 +33,18 @@ public interface FieldNameProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the sub entity the given field.
|
* Contains the sub entity the given field.
|
||||||
*
|
*
|
||||||
* @param propertyField
|
* @param propertyField
|
||||||
* the given field
|
* the given field
|
||||||
* @return <true> contains <false> contains not
|
* @return <true> contains <false> contains not
|
||||||
*/
|
*/
|
||||||
default boolean containsSubEntityAttribute(final String propertyField) {
|
default boolean containsSubEntityAttribute(final String propertyField) {
|
||||||
return FieldNameProvider.containsSubEntityAttribute(propertyField, getSubEntityAttributes());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
final List<String> subEntityAttributes = getSubEntityAttributes();
|
||||||
*
|
if (subEntityAttributes.contains(propertyField)) {
|
||||||
* @return all sub entities attributes.
|
|
||||||
*/
|
|
||||||
default List<String> getSubEntityAttributes() {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the database column for the key
|
|
||||||
*
|
|
||||||
* @return key fieldname
|
|
||||||
*/
|
|
||||||
default String getKeyFieldName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* the database column for the value
|
|
||||||
*
|
|
||||||
* @return key fieldname
|
|
||||||
*/
|
|
||||||
default String getValueFieldName() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is the entity field a {@link Map}.
|
|
||||||
*
|
|
||||||
* @return <true> is a map <false> is not a map
|
|
||||||
*/
|
|
||||||
default boolean isMap() {
|
|
||||||
return getKeyFieldName() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a sub attribute exists.
|
|
||||||
*
|
|
||||||
* @param propertyField
|
|
||||||
* the sub property field.
|
|
||||||
* @param subEntityAttribues
|
|
||||||
* the list of available properties
|
|
||||||
* @return <true> property exists <false> not exists
|
|
||||||
*/
|
|
||||||
static boolean containsSubEntityAttribute(final String propertyField, final List<String> subEntityAttribues) {
|
|
||||||
if (subEntityAttribues.contains(propertyField)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (final String attribute : subEntityAttribues) {
|
for (final String attribute : subEntityAttributes) {
|
||||||
final String[] graph = attribute.split("\\" + SUB_ATTRIBUTE_SEPERATOR);
|
final String[] graph = attribute.split("\\" + SUB_ATTRIBUTE_SEPERATOR);
|
||||||
|
|
||||||
for (final String subAttribute : graph) {
|
for (final String subAttribute : graph) {
|
||||||
@@ -102,4 +57,37 @@ public interface FieldNameProvider {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return all sub entities attributes.
|
||||||
|
*/
|
||||||
|
default List<String> getSubEntityAttributes() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The database column for the key
|
||||||
|
*
|
||||||
|
* @return key fieldname
|
||||||
|
*/
|
||||||
|
default String getKeyFieldName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The database column for the value
|
||||||
|
*
|
||||||
|
* @return key fieldname
|
||||||
|
*/
|
||||||
|
default String getValueFieldName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the entity field a {@link Map}.
|
||||||
|
*
|
||||||
|
* @return <true> is a map <false> is not a map
|
||||||
|
*/
|
||||||
|
default boolean isMap() {
|
||||||
|
return getKeyFieldName() != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import org.eclipse.hawkbit.repository.RepositoryConstants;
|
|||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
|
import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.ToManyStatusEntriesException;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
@@ -153,8 +154,8 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
|||||||
return handleAuthentifiactionMessage(message);
|
return handleAuthentifiactionMessage(message);
|
||||||
} catch (final IllegalArgumentException ex) {
|
} catch (final IllegalArgumentException ex) {
|
||||||
throw new AmqpRejectAndDontRequeueException("Invalid message!", ex);
|
throw new AmqpRejectAndDontRequeueException("Invalid message!", ex);
|
||||||
} catch (final TenantNotExistException teex) {
|
} catch (final TenantNotExistException | ToManyStatusEntriesException e) {
|
||||||
throw new AmqpRejectAndDontRequeueException(teex);
|
throw new AmqpRejectAndDontRequeueException(e);
|
||||||
} finally {
|
} finally {
|
||||||
SecurityContextHolder.setContext(oldContext);
|
SecurityContextHolder.setContext(oldContext);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ import java.util.Map;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Map} with attributes of SP Target.
|
* {@link Map} with attributes of SP Target.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class MgmtTargetAttributes extends HashMap<String, String> {
|
public class MgmtTargetAttributes extends HashMap<String, String> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,9 +52,7 @@ import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
|
|||||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||||
import org.eclipse.hawkbit.util.IpUtil;
|
import org.eclipse.hawkbit.util.IpUtil;
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
@@ -80,7 +78,6 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
|
|||||||
|
|
||||||
private static final String TARGET_DESCRIPTION_TEST = "created in test";
|
private static final String TARGET_DESCRIPTION_TEST = "created in test";
|
||||||
|
|
||||||
// json paths
|
|
||||||
private static final String JSON_PATH_ROOT = "$";
|
private static final String JSON_PATH_ROOT = "$";
|
||||||
|
|
||||||
// fields, attributes
|
// fields, attributes
|
||||||
@@ -633,69 +630,8 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
|
|||||||
final String knownName = "someName";
|
final String knownName = "someName";
|
||||||
createSingleTarget(knownControllerId, knownName);
|
createSingleTarget(knownControllerId, knownName);
|
||||||
|
|
||||||
// test
|
|
||||||
|
|
||||||
mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/installedDS"))
|
mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/installedDS"))
|
||||||
.andExpect(status().isNoContent()).andExpect(content().string(""));
|
.andExpect(status().isNoContent()).andExpect(content().string(""));
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore
|
|
||||||
public void getInstalledDistributionSetOfTarget() throws JSONException, Exception {
|
|
||||||
// create first a target which can be retrieved by rest interface
|
|
||||||
final String knownControllerId = "1";
|
|
||||||
final String knownName = "someName";
|
|
||||||
createSingleTarget(knownControllerId, knownName);
|
|
||||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
|
||||||
// assign ds to target
|
|
||||||
final Long actionId = deploymentManagement.assignDistributionSet(ds.getId(), knownControllerId).getActions()
|
|
||||||
.get(0);
|
|
||||||
// give feedback, so installedDS is in SNYC
|
|
||||||
feedbackToByInSync(actionId);
|
|
||||||
// test
|
|
||||||
|
|
||||||
final SoftwareModule os = ds.findFirstModuleByType(osType);
|
|
||||||
final SoftwareModule jvm = ds.findFirstModuleByType(runtimeType);
|
|
||||||
final SoftwareModule bApp = ds.findFirstModuleByType(appType);
|
|
||||||
mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/installedDS"))
|
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
|
||||||
.andExpect(jsonPath(JSON_PATH_ID, equalTo(ds.getId().intValue())))
|
|
||||||
.andExpect(jsonPath(JSON_PATH_NAME, equalTo(ds.getName())))
|
|
||||||
.andExpect(jsonPath(JSON_PATH_DESCRIPTION, equalTo(ds.getDescription())))
|
|
||||||
// os
|
|
||||||
.andExpect(
|
|
||||||
jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].id", equalTo(os.getId().intValue())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].name", equalTo(os.getName())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].description",
|
|
||||||
equalTo(os.getDescription())))
|
|
||||||
.andExpect(
|
|
||||||
jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].version", equalTo(os.getVersion())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].vendor", equalTo(os.getVendor())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + osType.getKey() + ")][0].type", equalTo("os")))
|
|
||||||
// jvm
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].id",
|
|
||||||
equalTo(jvm.getId().intValue())))
|
|
||||||
.andExpect(
|
|
||||||
jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].name", equalTo(jvm.getName())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].description",
|
|
||||||
equalTo(jvm.getDescription())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].version",
|
|
||||||
equalTo(jvm.getVersion())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].vendor",
|
|
||||||
equalTo(jvm.getVendor())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + runtimeType.getKey() + ")][0].type", equalTo("runtime")))
|
|
||||||
// baseApp
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].id",
|
|
||||||
equalTo(bApp.getId().intValue())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].name", equalTo(bApp.getName())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].description",
|
|
||||||
equalTo(bApp.getDescription())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].version",
|
|
||||||
equalTo(bApp.getVersion())))
|
|
||||||
.andExpect(
|
|
||||||
jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].vendor", equalTo(bApp.getVendor())))
|
|
||||||
.andExpect(jsonPath("$modules.[?(@.type==" + appType.getKey() + ")][0].type", equalTo("application")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -281,6 +281,16 @@ public interface DistributionSetManagement {
|
|||||||
Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId,
|
Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId,
|
||||||
@NotNull Pageable pageable);
|
@NotNull Pageable pageable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all meta data by the given distribution set id.
|
||||||
|
*
|
||||||
|
* @param distributionSetId
|
||||||
|
* the distribution set id to retrieve the meta data from
|
||||||
|
* @return list of distributionSetMetadata for a given distribution set Id.
|
||||||
|
*/
|
||||||
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||||
|
List<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* finds all meta data by the given distribution set id.
|
* finds all meta data by the given distribution set id.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -483,5 +483,23 @@ public interface SoftwareManagement {
|
|||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||||
SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm);
|
SoftwareModuleType updateSoftwareModuleType(@NotNull SoftwareModuleType sm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds all meta data by the given software module id.
|
||||||
|
*
|
||||||
|
* @param softwareModuleId
|
||||||
|
* the software module id to retrieve the meta data from
|
||||||
|
|
||||||
|
*
|
||||||
|
* @throws RSQLParameterUnsupportedFieldException
|
||||||
|
* if a field in the RSQL string is used but not provided by the
|
||||||
|
* given {@code fieldNameProvider}
|
||||||
|
* @throws RSQLParameterSyntaxException
|
||||||
|
* if the RSQL syntax is wrong
|
||||||
|
* @return result of all meta data entries for a given software
|
||||||
|
* module id.
|
||||||
|
*/
|
||||||
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
|
||||||
|
List<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(Long softwareModuleId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,18 +20,18 @@ import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
|||||||
public class AbstractPropertyChangeEvent<E extends TenantAwareBaseEntity> extends AbstractBaseEntityEvent<E> {
|
public class AbstractPropertyChangeEvent<E extends TenantAwareBaseEntity> extends AbstractBaseEntityEvent<E> {
|
||||||
|
|
||||||
private static final long serialVersionUID = -3671601415138242311L;
|
private static final long serialVersionUID = -3671601415138242311L;
|
||||||
private final transient Map<String, Values> changeSet;
|
private final transient Map<String, PropertyChange> changeSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize base entity and property changed with old and new value.
|
* Initialize base entity and property changed with old and new value.
|
||||||
*
|
*
|
||||||
* @param baseEntity
|
* @param baseEntity
|
||||||
* entity changed
|
* entity changed
|
||||||
* @param changeSetValues
|
* @param changeSetValues
|
||||||
* details of properties changed and old value and new value of
|
* details of properties changed and old value and new value of
|
||||||
* the changed properties
|
* the changed properties
|
||||||
*/
|
*/
|
||||||
public AbstractPropertyChangeEvent(final E baseEntity, final Map<String, Values> changeSetValues) {
|
public AbstractPropertyChangeEvent(final E baseEntity, final Map<String, PropertyChange> changeSetValues) {
|
||||||
super(baseEntity);
|
super(baseEntity);
|
||||||
this.changeSet = changeSetValues;
|
this.changeSet = changeSetValues;
|
||||||
}
|
}
|
||||||
@@ -39,27 +39,27 @@ public class AbstractPropertyChangeEvent<E extends TenantAwareBaseEntity> extend
|
|||||||
/**
|
/**
|
||||||
* @return the changeSet
|
* @return the changeSet
|
||||||
*/
|
*/
|
||||||
public Map<String, Values> getChangeSet() {
|
public Map<String, PropertyChange> getChangeSet() {
|
||||||
return changeSet;
|
return changeSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Carries old value and new value of a property .
|
* Carries old value and new value of a property .
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class Values {
|
public static class PropertyChange {
|
||||||
|
|
||||||
private final Object oldValue;
|
private final Object oldValue;
|
||||||
private final Object newValue;
|
private final Object newValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize old value and new changes value of property.
|
* Initialize old value and new changes value of property.
|
||||||
*
|
*
|
||||||
* @param oldValue
|
* @param oldValue
|
||||||
* old value before change
|
* old value before change
|
||||||
* @param newValue
|
* @param newValue
|
||||||
* new value after change
|
* new value after change
|
||||||
*/
|
*/
|
||||||
public Values(final Object oldValue, final Object newValue) {
|
public PropertyChange(final Object oldValue, final Object newValue) {
|
||||||
super();
|
super();
|
||||||
this.oldValue = oldValue;
|
this.oldValue = oldValue;
|
||||||
this.newValue = newValue;
|
this.newValue = newValue;
|
||||||
@@ -78,6 +78,5 @@ public class AbstractPropertyChangeEvent<E extends TenantAwareBaseEntity> extend
|
|||||||
public Object getNewValue() {
|
public Object getNewValue() {
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ public class ActionPropertyChangeEvent extends AbstractPropertyChangeEvent<Actio
|
|||||||
* @param action
|
* @param action
|
||||||
* @param changeSetValues
|
* @param changeSetValues
|
||||||
*/
|
*/
|
||||||
public ActionPropertyChangeEvent(final Action action,
|
public ActionPropertyChangeEvent(final Action action, final Map<String, PropertyChange> changeSetValues) {
|
||||||
final Map<String, AbstractPropertyChangeEvent<Action>.Values> changeSetValues) {
|
|
||||||
super(action, changeSetValues);
|
super(action, changeSetValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.eventbus.event;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the {@link AbstractBaseEntityEvent} of creating a new {@link DistributionSet}.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DistributionCreatedEvent extends AbstractBaseEntityEvent<DistributionSet> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param distributionSet
|
||||||
|
* the distributionSet which has been created
|
||||||
|
*/
|
||||||
|
public DistributionCreatedEvent(final DistributionSet distributionSet) {
|
||||||
|
super(distributionSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.eventbus.event;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.AbstractDistributedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the {@link AbstractDistributedEvent} for deletion of
|
||||||
|
* {@link DistributionSet}.
|
||||||
|
*/
|
||||||
|
public class DistributionDeletedEvent extends AbstractDistributedEvent {
|
||||||
|
private static final long serialVersionUID = -3308850381757843098L;
|
||||||
|
private final Long distributionId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tenant
|
||||||
|
* the tenant for this event
|
||||||
|
* @param distributionId
|
||||||
|
* the ID of the distribution set which has been deleted
|
||||||
|
*/
|
||||||
|
public DistributionDeletedEvent(final String tenant, final Long distributionId) {
|
||||||
|
super(-1, tenant);
|
||||||
|
this.distributionId = distributionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDistributionSetId() {
|
||||||
|
return distributionId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.eventbus.event;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the {@link AbstractBaseEntityEvent} for update a {@link DistributionSet}.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DistributionSetUpdateEvent extends AbstractBaseEntityEvent<DistributionSet> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param ds Distribution Set
|
||||||
|
*/
|
||||||
|
public DistributionSetUpdateEvent(final DistributionSet ds) {
|
||||||
|
super(ds);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,12 +20,12 @@ public class RolloutGroupPropertyChangeEvent extends AbstractPropertyChangeEvent
|
|||||||
private static final long serialVersionUID = 4026477044419472686L;
|
private static final long serialVersionUID = 4026477044419472686L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param rolloutGroup
|
* @param rolloutGroup
|
||||||
* @param changeSetValues
|
* @param changeSetValues
|
||||||
*/
|
*/
|
||||||
public RolloutGroupPropertyChangeEvent(final RolloutGroup rolloutGroup,
|
public RolloutGroupPropertyChangeEvent(final RolloutGroup rolloutGroup,
|
||||||
final Map<String, AbstractPropertyChangeEvent<RolloutGroup>.Values> changeSetValues) {
|
final Map<String, PropertyChange> changeSetValues) {
|
||||||
super(rolloutGroup, changeSetValues);
|
super(rolloutGroup, changeSetValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ public class RolloutPropertyChangeEvent extends AbstractPropertyChangeEvent<Roll
|
|||||||
private static final long serialVersionUID = 1056221355466373514L;
|
private static final long serialVersionUID = 1056221355466373514L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param rollout
|
* @param rollout
|
||||||
* @param changeSetValues
|
* @param changeSetValues
|
||||||
*/
|
*/
|
||||||
public RolloutPropertyChangeEvent(final Rollout rollout,
|
public RolloutPropertyChangeEvent(final Rollout rollout, final Map<String, PropertyChange> changeSetValues) {
|
||||||
final Map<String, AbstractPropertyChangeEvent<Rollout>.Values> changeSetValues) {
|
|
||||||
super(rollout, changeSetValues);
|
super(rollout, changeSetValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.eventbus.event;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.AbstractDistributedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Defines the {@link AbstractBaseEntityEvent} of deleting a {@link Target}.
|
||||||
|
*/
|
||||||
|
public class TargetDeletedEvent extends AbstractDistributedEvent {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final long targetId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tenant
|
||||||
|
* the tenant for this event
|
||||||
|
* @param targetId
|
||||||
|
* the ID of the target which has been deleted
|
||||||
|
*/
|
||||||
|
public TargetDeletedEvent(final String tenant, final long targetId) {
|
||||||
|
super(-1, tenant);
|
||||||
|
this.targetId = targetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the targetId
|
||||||
|
*/
|
||||||
|
public long getTargetId() {
|
||||||
|
return targetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.eventbus.event;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the {@link AbstractBaseEntityEvent} of updating a {@link Target}.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TargetUpdatedEvent extends AbstractBaseEntityEvent<Target> {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 5665118668865832477L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param baseEntity
|
||||||
|
* Target entity
|
||||||
|
*/
|
||||||
|
public TargetUpdatedEvent(final Target baseEntity) {
|
||||||
|
super(baseEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,16 +12,9 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* An abstract report series.
|
* An abstract report series.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class AbstractReportSeries implements Serializable {
|
public class AbstractReportSeries implements Serializable {
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|||||||
@@ -14,13 +14,11 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple list report series which just contains a list of values of a report.
|
* A simple list report series which just contains a list of values of a report.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class ListReportSeries extends AbstractReportSeries {
|
public class ListReportSeries extends AbstractReportSeries {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final List<Number> data = new ArrayList<>();
|
private final List<Number> data = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,8 +48,8 @@ public class ListReportSeries extends AbstractReportSeries {
|
|||||||
* @param values
|
* @param values
|
||||||
*/
|
*/
|
||||||
private void setData(final Number... values) {
|
private void setData(final Number... values) {
|
||||||
this.data.clear();
|
data.clear();
|
||||||
Collections.addAll(this.data, values);
|
Collections.addAll(data, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import org.springframework.data.jpa.repository.Modifying;
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Isolation;
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -599,11 +598,16 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<Action> findActionsByTarget(final String rsqlParam, final Target target, final Pageable pageable) {
|
public Page<Action> findActionsByTarget(final String rsqlParam, final Target target, final Pageable pageable) {
|
||||||
final Specification<JpaAction> specification = RSQLUtility.parse(rsqlParam, ActionFields.class);
|
|
||||||
|
|
||||||
return convertAcPage(actionRepository.findAll((Specification<JpaAction>) (root, query, cb) -> cb
|
final Specification<JpaAction> byTargetSpec = createSpecificationFor(target, rsqlParam);
|
||||||
.and(specification.toPredicate(root, query, cb), cb.equal(root.get(JpaAction_.target), target)),
|
final Page<JpaAction> actions = actionRepository.findAll(byTargetSpec, pageable);
|
||||||
pageable), pageable);
|
return convertAcPage(actions, pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Specification<JpaAction> createSpecificationFor(final Target target, final String rsqlParam) {
|
||||||
|
final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class);
|
||||||
|
return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
|
||||||
|
cb.equal(root.get(JpaAction_.target), target));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Page<Action> convertAcPage(final Page<JpaAction> findAll, final Pageable pageable) {
|
private static Page<Action> convertAcPage(final Page<JpaAction> findAll, final Pageable pageable) {
|
||||||
@@ -642,10 +646,7 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Long countActionsByTarget(final String rsqlParam, final Target target) {
|
public Long countActionsByTarget(final String rsqlParam, final Target target) {
|
||||||
final Specification<JpaAction> spec = RSQLUtility.parse(rsqlParam, ActionFields.class);
|
return actionRepository.count(createSpecificationFor(target, rsqlParam));
|
||||||
|
|
||||||
return actionRepository.count((root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
|
|
||||||
cb.equal(root.get(JpaAction_.target), target)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
|||||||
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
|
import org.eclipse.hawkbit.repository.DistributionSetTypeFields;
|
||||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||||
import org.eclipse.hawkbit.repository.TagManagement;
|
import org.eclipse.hawkbit.repository.TagManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagAssigmentResultEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagAssigmentResultEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityLockedException;
|
import org.eclipse.hawkbit.repository.exception.EntityLockedException;
|
||||||
@@ -54,6 +55,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
|
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageImpl;
|
import org.springframework.data.domain.PageImpl;
|
||||||
@@ -102,6 +104,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private AfterTransactionCommitExecutor afterCommit;
|
private AfterTransactionCommitExecutor afterCommit;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TenantAware tenantAware;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
|
public DistributionSet findDistributionSetByIdWithDetails(final Long distid) {
|
||||||
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid));
|
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid));
|
||||||
@@ -193,6 +198,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
// handle the empty list
|
// handle the empty list
|
||||||
distributionSetRepository.deleteByIdIn(toHardDelete);
|
distributionSetRepository.deleteByIdIn(toHardDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Arrays.stream(distributionSetIDs)
|
||||||
|
.forEach(dsId -> eventBus.post(new DistributionDeletedEvent(tenantAware.getCurrentTenant(), dsId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -475,11 +483,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
if (distributionSetMetadataRepository.exists(metadata.getId())) {
|
if (distributionSetMetadataRepository.exists(metadata.getId())) {
|
||||||
throwMetadataKeyAlreadyExists(metadata.getId().getKey());
|
throwMetadataKeyAlreadyExists(metadata.getId().getKey());
|
||||||
}
|
}
|
||||||
// merge base distribution set so optLockRevision gets updated and audit
|
|
||||||
// log written because
|
touch(metadata.getDistributionSet());
|
||||||
// modifying metadata is modifying the base distribution set itself for
|
|
||||||
// auditing purposes.
|
|
||||||
entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
|
|
||||||
return distributionSetMetadataRepository.save(metadata);
|
return distributionSetMetadataRepository.save(metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,7 +499,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
for (final JpaDistributionSetMetadata distributionSetMetadata : metadata) {
|
for (final JpaDistributionSetMetadata distributionSetMetadata : metadata) {
|
||||||
checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId());
|
checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId());
|
||||||
}
|
}
|
||||||
metadata.forEach(m -> entityManager.merge((JpaDistributionSet) m.getDistributionSet()).setLastModifiedAt(0L));
|
metadata.forEach(m -> touch(m.getDistributionSet()));
|
||||||
|
|
||||||
return new ArrayList<>(
|
return new ArrayList<>(
|
||||||
(Collection<? extends DistributionSetMetadata>) distributionSetMetadataRepository.save(metadata));
|
(Collection<? extends DistributionSetMetadata>) distributionSetMetadataRepository.save(metadata));
|
||||||
@@ -510,7 +515,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
findOne(metadata.getDistributionSet(), metadata.getKey());
|
findOne(metadata.getDistributionSet(), metadata.getKey());
|
||||||
// touch it to update the lock revision because we are modifying the
|
// touch it to update the lock revision because we are modifying the
|
||||||
// DS indirectly
|
// DS indirectly
|
||||||
entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L);
|
touch(metadata.getDistributionSet());
|
||||||
return distributionSetMetadataRepository.save(metadata);
|
return distributionSetMetadataRepository.save(metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,13 +523,29 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
|
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
|
||||||
@Modifying
|
@Modifying
|
||||||
public void deleteDistributionSetMetadata(final DistributionSet distributionSet, final String key) {
|
public void deleteDistributionSetMetadata(final DistributionSet distributionSet, final String key) {
|
||||||
|
touch(distributionSet);
|
||||||
distributionSetMetadataRepository.delete(new DsMetadataCompositeKey(distributionSet, key));
|
distributionSetMetadataRepository.delete(new DsMetadataCompositeKey(distributionSet, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to get the latest distribution set based on ds ID after the
|
||||||
|
* metadata changes for that distribution set.
|
||||||
|
*
|
||||||
|
* @param distributionSet
|
||||||
|
* Distribution set
|
||||||
|
*/
|
||||||
|
private void touch(final DistributionSet distributionSet) {
|
||||||
|
final DistributionSet latestDistributionSet = findDistributionSetById(distributionSet.getId());
|
||||||
|
// merge base distribution set so optLockRevision gets updated and audit
|
||||||
|
// log written because
|
||||||
|
// modifying metadata is modifying the base distribution set itself for
|
||||||
|
// auditing purposes.
|
||||||
|
entityManager.merge((JpaDistributionSet) latestDistributionSet).setLastModifiedAt(0L);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
||||||
final Pageable pageable) {
|
final Pageable pageable) {
|
||||||
|
|
||||||
return convertMdPage(distributionSetMetadataRepository
|
return convertMdPage(distributionSetMetadataRepository
|
||||||
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
|
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
|
||||||
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
|
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
|
||||||
@@ -532,6 +553,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
pageable);
|
pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId) {
|
||||||
|
return new ArrayList<>(distributionSetMetadataRepository
|
||||||
|
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
|
||||||
|
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
|
||||||
|
distributionSetId)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
public Page<DistributionSetMetadata> findDistributionSetMetadataByDistributionSetId(final Long distributionSetId,
|
||||||
final String rsqlParam, final Pageable pageable) {
|
final String rsqlParam, final Pageable pageable) {
|
||||||
|
|||||||
@@ -599,7 +599,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
|||||||
/**
|
/**
|
||||||
* Get count of targets in different status in rollout.
|
* Get count of targets in different status in rollout.
|
||||||
*
|
*
|
||||||
* @param page
|
* @param pageable
|
||||||
* the page request to sort and limit the result
|
* the page request to sort and limit the result
|
||||||
* @return a list of rollouts with details of targets count for different
|
* @return a list of rollouts with details of targets count for different
|
||||||
* statuses
|
* statuses
|
||||||
|
|||||||
@@ -621,6 +621,16 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
|||||||
pageable);
|
pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId) {
|
||||||
|
return new ArrayList<>(
|
||||||
|
softwareModuleMetadataRepository
|
||||||
|
.findAll((Specification<JpaSoftwareModuleMetadata>) (root, query,
|
||||||
|
cb) -> cb.and(cb.equal(
|
||||||
|
root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id),
|
||||||
|
softwareModuleId))));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SoftwareModuleMetadata findSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) {
|
public SoftwareModuleMetadata findSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) {
|
||||||
return findSoftwareModuleMetadata(new SwMetadataCompositeKey(softwareModule, key));
|
return findSoftwareModuleMetadata(new SwMetadataCompositeKey(softwareModule, key));
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import org.springframework.data.domain.Pageable;
|
|||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import org.springframework.data.jpa.domain.Specifications;
|
import org.springframework.data.jpa.domain.Specifications;
|
||||||
import org.springframework.data.jpa.repository.Modifying;
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Isolation;
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import javax.persistence.criteria.Root;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.repository.TargetFields;
|
import org.eclipse.hawkbit.repository.TargetFields;
|
||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagAssigmentResultEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagAssigmentResultEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
@@ -48,6 +49,7 @@ import org.eclipse.hawkbit.repository.model.TargetIdName;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.cache.annotation.CacheEvict;
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -94,6 +96,9 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private EventBus eventBus;
|
private EventBus eventBus;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TenantAware tenantAware;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AfterTransactionCommitExecutor afterCommit;
|
private AfterTransactionCommitExecutor afterCommit;
|
||||||
|
|
||||||
@@ -206,6 +211,8 @@ public class JpaTargetManagement implements TargetManagement {
|
|||||||
targetInfoRepository.deleteByTargetIdIn(targetsForCurrentTenant);
|
targetInfoRepository.deleteByTargetIdIn(targetsForCurrentTenant);
|
||||||
targetRepository.deleteByIdIn(targetsForCurrentTenant);
|
targetRepository.deleteByIdIn(targetsForCurrentTenant);
|
||||||
}
|
}
|
||||||
|
targetsForCurrentTenant
|
||||||
|
.forEach(targetId -> eventBus.post(new TargetDeletedEvent(tenantAware.getCurrentTenant(), targetId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import org.springframework.transaction.TransactionSystemException;
|
|||||||
*/
|
*/
|
||||||
@Aspect
|
@Aspect
|
||||||
public class ExceptionMappingAspectHandler implements Ordered {
|
public class ExceptionMappingAspectHandler implements Ordered {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ExceptionMappingAspectHandler.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ExceptionMappingAspectHandler.class);
|
||||||
|
|
||||||
private static final Map<String, String> EXCEPTION_MAPPING = new HashMap<>();
|
private static final Map<String, String> EXCEPTION_MAPPING = new HashMap<>();
|
||||||
@@ -63,6 +64,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
|
|||||||
private final SQLStateSQLExceptionTranslator sqlStateExceptionTranslator = new SQLStateSQLExceptionTranslator();
|
private final SQLStateSQLExceptionTranslator sqlStateExceptionTranslator = new SQLStateSQLExceptionTranslator();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
||||||
MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class);
|
MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class);
|
||||||
MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class);
|
MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class);
|
||||||
MAPPED_EXCEPTION_ORDER.add(ConcurrencyFailureException.class);
|
MAPPED_EXCEPTION_ORDER.add(ConcurrencyFailureException.class);
|
||||||
@@ -90,9 +92,11 @@ public class ExceptionMappingAspectHandler implements Ordered {
|
|||||||
+ " || execution( * org.eclipse.hawkbit.controller.*.*(..)) "
|
+ " || execution( * org.eclipse.hawkbit.controller.*.*(..)) "
|
||||||
+ " || execution( * org.eclipse.hawkbit.rest.resource.*.*(..)) "
|
+ " || execution( * org.eclipse.hawkbit.rest.resource.*.*(..)) "
|
||||||
+ " || execution( * org.eclipse.hawkbit.service.*.*(..)) )", throwing = "ex")
|
+ " || execution( * org.eclipse.hawkbit.service.*.*(..)) )", throwing = "ex")
|
||||||
// Exception squid:S00112 - Is aspectJ proxy
|
// Exception for squid:S00112, squid:S1162
|
||||||
@SuppressWarnings({ "squid:S00112" })
|
// It is a AspectJ proxy which deals with exceptions.
|
||||||
|
@SuppressWarnings({ "squid:S00112", "squid:S1162" })
|
||||||
public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable {
|
public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable {
|
||||||
|
|
||||||
LOG.trace("exception occured", ex);
|
LOG.trace("exception occured", ex);
|
||||||
Exception translatedAccessException = translateEclipseLinkExceptionIfPossible(ex);
|
Exception translatedAccessException = translateEclipseLinkExceptionIfPossible(ex);
|
||||||
|
|
||||||
@@ -122,6 +126,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.trace("mapped exception {} to {}", translatedAccessException.getClass(), mappingException.getClass());
|
LOG.trace("mapped exception {} to {}", translatedAccessException.getClass(), mappingException.getClass());
|
||||||
throw mappingException;
|
throw mappingException;
|
||||||
}
|
}
|
||||||
@@ -138,7 +143,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
|
|||||||
* translate the exception by the sql error code. Luckily, there we can use
|
* translate the exception by the sql error code. Luckily, there we can use
|
||||||
* {@link SQLStateSQLExceptionTranslator} if we can get a
|
* {@link SQLStateSQLExceptionTranslator} if we can get a
|
||||||
* {@link SQLException}.
|
* {@link SQLException}.
|
||||||
*
|
*
|
||||||
* @param accessException
|
* @param accessException
|
||||||
* the base access exception from jpa
|
* the base access exception from jpa
|
||||||
* @return the translated accessException
|
* @return the translated accessException
|
||||||
|
|||||||
@@ -1,154 +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.repository.jpa.eventbus;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
|
|
||||||
import org.aspectj.lang.ProceedingJoinPoint;
|
|
||||||
import org.aspectj.lang.annotation.Around;
|
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
|
||||||
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.TargetRepository;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
|
||||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
|
||||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An aspect implementation which wraps the necessary repository services for
|
|
||||||
* saving {@link TenantAwareBaseEntity}s to publish create or update events.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
@Aspect
|
|
||||||
public class EntityChangeEventListener {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EventBus eventBus;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private TenantAware tenantAware;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private EntityManager entityManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AfterTransactionCommitExecutor afterCommit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In case the a {@link Target} is created a corresponding
|
|
||||||
* {@link TargetInfo} is created as well. We need the {@link TargetInfo}
|
|
||||||
* information in the target created event. So we are listening to the
|
|
||||||
* {@link TargetInfo} creation to indicate if an Target has been created.
|
|
||||||
*
|
|
||||||
* @param joinpoint
|
|
||||||
* the aspect join point
|
|
||||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
|
||||||
* @throws Throwable
|
|
||||||
* in case exception happens in the
|
|
||||||
* {@link ProceedingJoinPoint#proceed()}
|
|
||||||
*/
|
|
||||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetInfoRepository.save(..))")
|
|
||||||
// Exception squid:S00112 - Is aspectJ proxy
|
|
||||||
@SuppressWarnings({ "squid:S00112" })
|
|
||||||
public Object targetCreated(final ProceedingJoinPoint joinpoint) throws Throwable {
|
|
||||||
final boolean isNew = isTargetInfoNew(joinpoint.getArgs()[0]);
|
|
||||||
final Object result = joinpoint.proceed();
|
|
||||||
if (result instanceof TargetInfo) {
|
|
||||||
if (isNew) {
|
|
||||||
notifyTargetCreated(entityManager.merge(entityManager.merge(((TargetInfo) result).getTarget())));
|
|
||||||
} else {
|
|
||||||
notifyTargetInfoChanged((TargetInfo) result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy method around the delete method of the {@link TargetRepository} to
|
|
||||||
* notify the {@link TargetDeletedEvent} in case targets has been deleted.
|
|
||||||
*
|
|
||||||
* @param joinpoint
|
|
||||||
* the aspect join point
|
|
||||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
|
||||||
* @throws Throwable
|
|
||||||
* in case exception happens in the
|
|
||||||
* {@link ProceedingJoinPoint#proceed()}
|
|
||||||
*/
|
|
||||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.deleteByIdIn(..))")
|
|
||||||
// Exception squid:S00112 - Is aspectJ proxy
|
|
||||||
@SuppressWarnings({ "squid:S00112" })
|
|
||||||
public Object targetDeletedById(final ProceedingJoinPoint joinpoint) throws Throwable {
|
|
||||||
final String currentTenant = tenantAware.getCurrentTenant();
|
|
||||||
final Object result = joinpoint.proceed();
|
|
||||||
final Collection<Long> targetIds = (Collection<Long>) joinpoint.getArgs()[0];
|
|
||||||
targetIds.forEach(targetId -> notifyTargetDeleted(currentTenant, targetId));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Proxy method around the delete method of the {@link TargetRepository} to
|
|
||||||
* notify the {@link TargetDeletedEvent} in case targets has been deleted.
|
|
||||||
*
|
|
||||||
* @param joinpoint
|
|
||||||
* the aspect join point
|
|
||||||
* @return the object of the {@link ProceedingJoinPoint#proceed()}
|
|
||||||
* @throws Throwable
|
|
||||||
* in case exception happens in the
|
|
||||||
* {@link ProceedingJoinPoint#proceed()}
|
|
||||||
*/
|
|
||||||
@Around("execution(* org.eclipse.hawkbit.repository.jpa.TargetRepository.delete(..))")
|
|
||||||
// Exception squid:S00112 - Is aspectJ proxy
|
|
||||||
@SuppressWarnings({ "squid:S00112", "unchecked" })
|
|
||||||
public Object targetDeleted(final ProceedingJoinPoint joinpoint) throws Throwable {
|
|
||||||
final String currentTenant = tenantAware.getCurrentTenant();
|
|
||||||
final Object result = joinpoint.proceed();
|
|
||||||
final Object param = joinpoint.getArgs()[0];
|
|
||||||
// delete by id
|
|
||||||
if (param instanceof Long) {
|
|
||||||
notifyTargetDeleted(currentTenant, (Long) param);
|
|
||||||
} else if (param instanceof Target) {
|
|
||||||
notifyTargetDeleted(currentTenant, ((Target) param).getId());
|
|
||||||
} else if (param instanceof Iterable) {
|
|
||||||
((Iterable<Target>) param).forEach(target -> notifyTargetDeleted(currentTenant, target.getId()));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyTargetCreated(final Target t) {
|
|
||||||
afterCommit.afterCommit(() -> eventBus.post(new TargetCreatedEvent(t)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyTargetInfoChanged(final TargetInfo targetInfo) {
|
|
||||||
afterCommit.afterCommit(() -> eventBus.post(new TargetInfoUpdateEvent(targetInfo)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyTargetDeleted(final String tenant, final Long targetId) {
|
|
||||||
afterCommit.afterCommit(() -> eventBus.post(new TargetDeletedEvent(tenant, targetId)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isTargetInfoNew(final Object targetInfo) {
|
|
||||||
return ((JpaTargetInfo) targetInfo).isNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -179,4 +179,5 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,79 +8,47 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.model;
|
package org.eclipse.hawkbit.repository.jpa.model;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
|
||||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
|
||||||
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
|
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
|
||||||
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
|
||||||
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
|
||||||
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens to change in property values of an entity.
|
* Listens to change in property values of an entity and calls the corresponding
|
||||||
|
* {@link EventAwareEntity}.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class EntityPropertyChangeListener extends DescriptorEventAdapter {
|
public class EntityPropertyChangeListener extends DescriptorEventAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postInsert(final DescriptorEvent event) {
|
public void postInsert(final DescriptorEvent event) {
|
||||||
if (event.getObject().getClass().equals(Action.class)) {
|
final Object object = event.getObject();
|
||||||
final Action action = (Action) event.getObject();
|
if (isEventAwareEntity(object)) {
|
||||||
if (action.getRollout() != null) {
|
doNotifiy(() -> ((EventAwareEntity) object).fireCreateEvent(event));
|
||||||
final EventBus eventBus = getEventBus();
|
|
||||||
final AfterTransactionCommitExecutor afterCommit = getAfterTransactionCommmitExecutor();
|
|
||||||
afterCommit.afterCommit(() -> eventBus.post(new ActionCreatedEvent(action)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postUpdate(final DescriptorEvent event) {
|
public void postUpdate(final DescriptorEvent event) {
|
||||||
if (event.getObject().getClass().equals(JpaAction.class)) {
|
final Object object = event.getObject();
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(() -> getEventBus().post(
|
if (isEventAwareEntity(object)) {
|
||||||
new ActionPropertyChangeEvent((Action) event.getObject(), getChangeSet(Action.class, event))));
|
doNotifiy(() -> ((EventAwareEntity) object).fireUpdateEvent(event));
|
||||||
} else if (event.getObject().getClass().equals(JpaRollout.class)) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(() -> getEventBus().post(
|
|
||||||
new RolloutPropertyChangeEvent((Rollout) event.getObject(), getChangeSet(Rollout.class, event))));
|
|
||||||
} else if (event.getObject().getClass().equals(JpaRolloutGroup.class)) {
|
|
||||||
getAfterTransactionCommmitExecutor().afterCommit(
|
|
||||||
() -> getEventBus().post(new RolloutGroupPropertyChangeEvent((RolloutGroup) event.getObject(),
|
|
||||||
getChangeSet(RolloutGroup.class, event))));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends TenantAwareBaseEntity> Map<String, AbstractPropertyChangeEvent<T>.Values> getChangeSet(
|
@Override
|
||||||
final Class<T> clazz, final DescriptorEvent event) {
|
public void postDelete(final DescriptorEvent event) {
|
||||||
final T rolloutGroup = clazz.cast(event.getObject());
|
final Object object = event.getObject();
|
||||||
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
if (isEventAwareEntity(object)) {
|
||||||
return changeSet.getChanges().stream().filter(record -> record instanceof DirectToFieldChangeRecord)
|
doNotifiy(() -> ((EventAwareEntity) object).fireDeleteEvent(event));
|
||||||
.map(record -> (DirectToFieldChangeRecord) record)
|
}
|
||||||
.collect(Collectors.toMap(record -> record.getAttribute(),
|
|
||||||
record -> new AbstractPropertyChangeEvent<T>(rolloutGroup, null).new Values(
|
|
||||||
record.getOldValue(), record.getNewValue())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AfterTransactionCommitExecutor getAfterTransactionCommmitExecutor() {
|
private static boolean isEventAwareEntity(final Object object) {
|
||||||
return AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit();
|
return object instanceof EventAwareEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventBus getEventBus() {
|
private static void doNotifiy(final Runnable runnable) {
|
||||||
return EventBusHolder.getInstance().getEventBus();
|
AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.jpa.model;
|
||||||
|
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interfaces which can be implemented by entities to be called when the entity
|
||||||
|
* should fire an event because the entity has been created, updated or deleted.
|
||||||
|
*/
|
||||||
|
public interface EventAwareEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired for the Entity creation.
|
||||||
|
*
|
||||||
|
* @param descriptorEvent
|
||||||
|
*/
|
||||||
|
void fireCreateEvent(DescriptorEvent descriptorEvent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired for the Entity updation.
|
||||||
|
*
|
||||||
|
* @param descriptorEvent
|
||||||
|
*/
|
||||||
|
void fireUpdateEvent(DescriptorEvent descriptorEvent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired for the Entity deletion.
|
||||||
|
*
|
||||||
|
* @param descriptorEvent
|
||||||
|
*/
|
||||||
|
void fireDeleteEvent(DescriptorEvent descriptorEvent);
|
||||||
|
}
|
||||||
@@ -28,6 +28,10 @@ import javax.persistence.NamedSubgraph;
|
|||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.ActionCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.ActionPropertyChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -35,6 +39,7 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
|||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA implementation of {@link Action}.
|
* JPA implementation of {@link Action}.
|
||||||
@@ -49,7 +54,7 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action {
|
public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action, EventAwareEntity {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@@ -171,4 +176,20 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
|||||||
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
|
return "Action [distributionSet=" + distributionSet + ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new ActionCreatedEvent(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new ActionPropertyChangeEvent(this,
|
||||||
|
EntityPropertyChangeHelper.getChangeSet(Action.class, descriptorEvent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no action deletion
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements
|
|||||||
* the status for this action status
|
* the status for this action status
|
||||||
* @param occurredAt
|
* @param occurredAt
|
||||||
* the occurred timestamp
|
* the occurred timestamp
|
||||||
* @param messages
|
* @param message
|
||||||
* the messages which should be added to this action status
|
* the message which should be added to this action status
|
||||||
*/
|
*/
|
||||||
public JpaActionStatus(final JpaAction action, final Status status, final Long occurredAt, final String message) {
|
public JpaActionStatus(final JpaAction action, final Status status, final Long occurredAt, final String message) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -33,8 +34,14 @@ import javax.persistence.OneToMany;
|
|||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent.PropertyChange;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
||||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||||
@@ -45,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
|||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Jpa implementation of {@link DistributionSet}.
|
* Jpa implementation of {@link DistributionSet}.
|
||||||
@@ -61,9 +69,13 @@ import org.eclipse.persistence.annotations.CascadeOnDelete;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet {
|
public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implements DistributionSet, EventAwareEntity {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final String COMPLETE_PROPERTY = "complete";
|
||||||
|
|
||||||
|
private static final String DELETED_PROPERTY = "deleted";
|
||||||
|
|
||||||
@Column(name = "required_migration_step")
|
@Column(name = "required_migration_step")
|
||||||
private boolean requiredMigrationStep;
|
private boolean requiredMigrationStep;
|
||||||
|
|
||||||
@@ -279,4 +291,30 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
|||||||
return complete;
|
return complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new DistributionCreatedEvent(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
|
||||||
|
final Map<String, PropertyChange> changeSet = EntityPropertyChangeHelper.getChangeSet(JpaDistributionSet.class,
|
||||||
|
descriptorEvent);
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new DistributionSetUpdateEvent(this));
|
||||||
|
|
||||||
|
if (changeSet.containsKey(DELETED_PROPERTY)) {
|
||||||
|
final Boolean newDeleted = (Boolean) changeSet.get(DELETED_PROPERTY).getNewValue();
|
||||||
|
if (newDeleted) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new DistributionDeletedEvent(getTenant(), getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new DistributionDeletedEvent(getTenant(), getId()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,17 @@ import javax.persistence.Table;
|
|||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.RolloutPropertyChangeEvent;
|
||||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
|
import org.eclipse.hawkbit.repository.jpa.cache.CacheField;
|
||||||
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
|
import org.eclipse.hawkbit.repository.jpa.cache.CacheKeys;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA implementation of a {@link Rollout}.
|
* JPA implementation of a {@link Rollout}.
|
||||||
@@ -44,7 +48,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, EventAwareEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -197,4 +201,21 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout {
|
|||||||
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
|
+ ", getName()=" + getName() + ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no rollout creation event
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new RolloutPropertyChangeEvent(this,
|
||||||
|
EntityPropertyChangeHelper.getChangeSet(Rollout.class, descriptorEvent)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no rollout deletion event
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,13 @@ import javax.persistence.Table;
|
|||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
import javax.persistence.UniqueConstraint;
|
import javax.persistence.UniqueConstraint;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupPropertyChangeEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EntityPropertyChangeHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA entity definition of persisting a group of an rollout.
|
* JPA entity definition of persisting a group of an rollout.
|
||||||
@@ -40,7 +44,7 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup {
|
public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup, EventAwareEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@@ -236,4 +240,19 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr
|
|||||||
+ ", getId()=" + getId() + "]";
|
+ ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no RolloutGroup created event
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new RolloutGroupPropertyChangeEvent(this,
|
||||||
|
EntityPropertyChangeHelper.getChangeSet(RolloutGroup.class, descriptorEvent)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no RolloutGroup deleted event
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ import javax.validation.constraints.NotNull;
|
|||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityChecker;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||||
@@ -45,6 +49,7 @@ import org.eclipse.hawkbit.repository.model.Target;
|
|||||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
import org.springframework.data.domain.Persistable;
|
import org.springframework.data.domain.Persistable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,7 +69,8 @@ import org.springframework.data.domain.Persistable;
|
|||||||
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for
|
||||||
// sub entities
|
// sub entities
|
||||||
@SuppressWarnings("squid:S2160")
|
@SuppressWarnings("squid:S2160")
|
||||||
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target {
|
public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Long>, Target, EventAwareEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Column(name = "controller_id", length = 64)
|
@Column(name = "controller_id", length = 64)
|
||||||
@@ -180,7 +186,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isNew
|
* @param entityNew
|
||||||
* the isNew to set
|
* the isNew to set
|
||||||
*/
|
*/
|
||||||
public void setNew(final boolean entityNew) {
|
public void setNew(final boolean entityNew) {
|
||||||
@@ -222,6 +228,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
|||||||
* @param securityToken
|
* @param securityToken
|
||||||
* the securityToken to set
|
* the securityToken to set
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void setSecurityToken(final String securityToken) {
|
public void setSecurityToken(final String securityToken) {
|
||||||
this.securityToken = securityToken;
|
this.securityToken = securityToken;
|
||||||
}
|
}
|
||||||
@@ -231,4 +238,18 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable<Lon
|
|||||||
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
|
return "Target [controllerId=" + controllerId + ", getId()=" + getId() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new TargetCreatedEvent(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new TargetUpdatedEvent(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new TargetDeletedEvent(getTenant(), getId()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import javax.persistence.Column;
|
|||||||
import javax.persistence.ConstraintMode;
|
import javax.persistence.ConstraintMode;
|
||||||
import javax.persistence.ElementCollection;
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EntityListeners;
|
||||||
import javax.persistence.EnumType;
|
import javax.persistence.EnumType;
|
||||||
import javax.persistence.Enumerated;
|
import javax.persistence.Enumerated;
|
||||||
import javax.persistence.FetchType;
|
import javax.persistence.FetchType;
|
||||||
@@ -37,7 +38,9 @@ import javax.persistence.OneToOne;
|
|||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -48,6 +51,7 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
|||||||
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||||
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
import org.eclipse.persistence.annotations.CascadeOnDelete;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.domain.Persistable;
|
import org.springframework.data.domain.Persistable;
|
||||||
@@ -64,7 +68,8 @@ import org.springframework.data.domain.Persistable;
|
|||||||
@Table(name = "sp_target_info", indexes = {
|
@Table(name = "sp_target_info", indexes = {
|
||||||
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
|
@Index(name = "sp_idx_target_info_02", columnList = "target_id,update_status") })
|
||||||
@Entity
|
@Entity
|
||||||
public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
@EntityListeners(EntityPropertyChangeListener.class)
|
||||||
|
public class JpaTargetInfo implements Persistable<Long>, TargetInfo, EventAwareEntity {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
|
private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class);
|
||||||
@@ -117,7 +122,7 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
|||||||
private boolean requestControllerAttributes = true;
|
private boolean requestControllerAttributes = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for {@link TargetStatus}.
|
* Constructor for {@link JpaTargetInfo}.
|
||||||
*
|
*
|
||||||
* @param target
|
* @param target
|
||||||
* related to this status.
|
* related to this status.
|
||||||
@@ -144,7 +149,7 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param isNew
|
* @param entityNew
|
||||||
* the isNew to set
|
* the isNew to set
|
||||||
*/
|
*/
|
||||||
public void setNew(final boolean entityNew) {
|
public void setNew(final boolean entityNew) {
|
||||||
@@ -321,4 +326,19 @@ public class JpaTargetInfo implements Persistable<Long>, TargetInfo {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no target info created event
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
EventBusHolder.getInstance().getEventBus().post(new TargetInfoUpdateEvent(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireDeleteEvent(final DescriptorEvent descriptorEvent) {
|
||||||
|
// there is no target info deleted event
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.jpa.model.helper;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent.PropertyChange;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||||
|
import org.eclipse.persistence.descriptors.DescriptorEvent;
|
||||||
|
import org.eclipse.persistence.internal.sessions.ObjectChangeSet;
|
||||||
|
import org.eclipse.persistence.queries.UpdateObjectQuery;
|
||||||
|
import org.eclipse.persistence.sessions.changesets.DirectToFieldChangeRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to get the change set for the property changes in the Entity.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public class EntityPropertyChangeHelper<T extends TenantAwareBaseEntity> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To get the map of entity property change set
|
||||||
|
*
|
||||||
|
* @param clazz
|
||||||
|
* @param event
|
||||||
|
* @return the map of the changeSet
|
||||||
|
*/
|
||||||
|
public static <T extends TenantAwareBaseEntity> Map<String, PropertyChange> getChangeSet(final Class<T> clazz,
|
||||||
|
final DescriptorEvent event) {
|
||||||
|
final T rolloutGroup = clazz.cast(event.getObject());
|
||||||
|
final ObjectChangeSet changeSet = ((UpdateObjectQuery) event.getQuery()).getObjectChangeSet();
|
||||||
|
return changeSet.getChanges().stream().filter(record -> record instanceof DirectToFieldChangeRecord)
|
||||||
|
.map(record -> (DirectToFieldChangeRecord) record)
|
||||||
|
.collect(Collectors.toMap(record -> record.getAttribute(),
|
||||||
|
record -> new PropertyChange(record.getOldValue(), record.getNewValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.repository.FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -15,7 +17,6 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Expression;
|
import javax.persistence.criteria.Expression;
|
||||||
@@ -49,7 +50,7 @@ import cz.jirutka.rsql.parser.ast.RSQLVisitor;
|
|||||||
* A utility class which is able to parse RSQL strings into an spring data
|
* A utility class which is able to parse RSQL strings into an spring data
|
||||||
* {@link Specification} which then can be enhanced sql queries to filter
|
* {@link Specification} which then can be enhanced sql queries to filter
|
||||||
* entities. RSQL parser library: https://github.com/jirutka/rsql-parser
|
* entities. RSQL parser library: https://github.com/jirutka/rsql-parser
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Equal to : ==</li>
|
* <li>Equal to : ==</li>
|
||||||
* <li>Not equal to : !=</li>
|
* <li>Not equal to : !=</li>
|
||||||
@@ -83,14 +84,12 @@ public final class RSQLUtility {
|
|||||||
/**
|
/**
|
||||||
* parses an RSQL valid string into an JPA {@link Specification} which then
|
* parses an RSQL valid string into an JPA {@link Specification} which then
|
||||||
* can be used to filter for JPA entities with the given RSQL query.
|
* can be used to filter for JPA entities with the given RSQL query.
|
||||||
*
|
*
|
||||||
* @param rsql
|
* @param rsql
|
||||||
* the rsql query
|
* the rsql query
|
||||||
* @param fieldNameProvider
|
* @param fieldNameProvider
|
||||||
* the enum class type which implements the
|
* the enum class type which implements the
|
||||||
* {@link FieldNameProvider}
|
* {@link FieldNameProvider}
|
||||||
* @param entityManager
|
|
||||||
* {@link EntityManager}
|
|
||||||
* @return an specification which can be used with JPA
|
* @return an specification which can be used with JPA
|
||||||
* @throws RSQLParameterUnsupportedFieldException
|
* @throws RSQLParameterUnsupportedFieldException
|
||||||
* if a field in the RSQL string is used but not provided by the
|
* if a field in the RSQL string is used but not provided by the
|
||||||
@@ -105,10 +104,10 @@ public final class RSQLUtility {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the given rsql string regarding existence and correct syntax.
|
* Validate the given rsql string regarding existence and correct syntax.
|
||||||
*
|
*
|
||||||
* @param rsql
|
* @param rsql
|
||||||
* the rsql string to get validated
|
* the rsql string to get validated
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static void isValid(final String rsql) {
|
public static void isValid(final String rsql) {
|
||||||
parseRsql(rsql);
|
parseRsql(rsql);
|
||||||
@@ -156,7 +155,7 @@ public final class RSQLUtility {
|
|||||||
/**
|
/**
|
||||||
* An implementation of the {@link RSQLVisitor} to visit the parsed tokens
|
* An implementation of the {@link RSQLVisitor} to visit the parsed tokens
|
||||||
* and build jpa where clauses.
|
* and build jpa where clauses.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param <A>
|
* @param <A>
|
||||||
@@ -205,7 +204,7 @@ public final class RSQLUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
|
private String getAndValidatePropertyFieldName(final A propertyEnum, final ComparisonNode node) {
|
||||||
String finalProperty = propertyEnum.getFieldName();
|
|
||||||
final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
|
final String[] graph = node.getSelector().split("\\" + FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR);
|
||||||
|
|
||||||
validateMapParamter(propertyEnum, node, graph);
|
validateMapParamter(propertyEnum, node, graph);
|
||||||
@@ -215,9 +214,12 @@ public final class RSQLUtility {
|
|||||||
throw createRSQLParameterUnsupportedException(node);
|
throw createRSQLParameterUnsupportedException(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final StringBuilder fieldNameBuilder = new StringBuilder(propertyEnum.getFieldName());
|
||||||
|
|
||||||
for (int i = 1; i < graph.length; i++) {
|
for (int i = 1; i < graph.length; i++) {
|
||||||
|
|
||||||
final String propertyField = graph[i];
|
final String propertyField = graph[i];
|
||||||
finalProperty += FieldNameProvider.SUB_ATTRIBUTE_SEPERATOR + propertyField;
|
fieldNameBuilder.append(SUB_ATTRIBUTE_SEPERATOR).append(propertyField);
|
||||||
|
|
||||||
// the key of map is not in the graph
|
// the key of map is not in the graph
|
||||||
if (propertyEnum.isMap() && graph.length == (i + 1)) {
|
if (propertyEnum.isMap() && graph.length == (i + 1)) {
|
||||||
@@ -229,7 +231,7 @@ public final class RSQLUtility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalProperty;
|
return fieldNameBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateMapParamter(final A propertyEnum, final ComparisonNode node, final String[] graph) {
|
private void validateMapParamter(final A propertyEnum, final ComparisonNode node, final String[] graph) {
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
/**
|
||||||
|
* 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.repository.jpa.eventbus;
|
||||||
|
|
||||||
|
import static org.fest.assertions.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||||
|
import org.fest.assertions.api.Assertions;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.EventBus;
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
|
||||||
|
import ru.yandex.qatools.allure.annotations.Description;
|
||||||
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
|
import ru.yandex.qatools.allure.annotations.Stories;
|
||||||
|
|
||||||
|
@Features("Component Tests - Repository")
|
||||||
|
@Stories("Entity Events")
|
||||||
|
public class RepositoryEntityEventTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EventBus eventBus;
|
||||||
|
|
||||||
|
private final MyEventListener eventListener = new MyEventListener();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void beforeTest() {
|
||||||
|
eventListener.queue.clear();
|
||||||
|
eventBus.register(eventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that the target created event is published when a target has been created")
|
||||||
|
public void targetCreatedEventIsPublished() throws InterruptedException {
|
||||||
|
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||||
|
|
||||||
|
final TargetCreatedEvent targetCreatedEvent = eventListener.waitForEvent(TargetCreatedEvent.class, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
assertThat(targetCreatedEvent).isNotNull();
|
||||||
|
assertThat(targetCreatedEvent.getEntity().getId()).isEqualTo(createdTarget.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that the target update event is published when a target has been updated")
|
||||||
|
public void targetUpdateEventIsPublished() throws InterruptedException {
|
||||||
|
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||||
|
createdTarget.setName("updateName");
|
||||||
|
targetManagement.updateTarget(createdTarget);
|
||||||
|
|
||||||
|
final TargetUpdatedEvent targetUpdatedEvent = eventListener.waitForEvent(TargetUpdatedEvent.class, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
assertThat(targetUpdatedEvent).isNotNull();
|
||||||
|
assertThat(targetUpdatedEvent.getEntity().getId()).isEqualTo(createdTarget.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that the target info update event is published when a target info has been updated")
|
||||||
|
public void targetInfoUpdateEventIsPublished() throws InterruptedException {
|
||||||
|
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||||
|
controllerManagament.updateTargetStatus(createdTarget.getTargetInfo(), TargetUpdateStatus.PENDING,
|
||||||
|
System.currentTimeMillis(), URI.create("http://127.0.0.1"));
|
||||||
|
|
||||||
|
final TargetInfoUpdateEvent targetInfoUpdatedEvent = eventListener.waitForEvent(TargetInfoUpdateEvent.class, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
assertThat(targetInfoUpdatedEvent).isNotNull();
|
||||||
|
assertThat(targetInfoUpdatedEvent.getEntity().getTarget().getId()).isEqualTo(createdTarget.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that the target deleted event is published when a target has been deleted")
|
||||||
|
public void targetDeletedEventIsPublished() throws InterruptedException {
|
||||||
|
final Target createdTarget = targetManagement.createTarget(entityFactory.generateTarget("12345"));
|
||||||
|
|
||||||
|
targetManagement.deleteTargets(createdTarget.getId());
|
||||||
|
|
||||||
|
final TargetDeletedEvent targetDeletedEvent = eventListener.waitForEvent(TargetDeletedEvent.class, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
assertThat(targetDeletedEvent).isNotNull();
|
||||||
|
assertThat(targetDeletedEvent.getTargetId()).isEqualTo(createdTarget.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that the distribution set created event is published when a distribution set has been created")
|
||||||
|
public void distributionSetCreatedEventIsPublished() throws InterruptedException {
|
||||||
|
final DistributionSet generateDistributionSet = entityFactory.generateDistributionSet();
|
||||||
|
generateDistributionSet.setName("dsEventTest");
|
||||||
|
generateDistributionSet.setVersion("1");
|
||||||
|
final DistributionSet createDistributionSet = distributionSetManagement
|
||||||
|
.createDistributionSet(generateDistributionSet);
|
||||||
|
|
||||||
|
final DistributionCreatedEvent dsCreatedEvent = eventListener.waitForEvent(DistributionCreatedEvent.class, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
assertThat(dsCreatedEvent).isNotNull();
|
||||||
|
assertThat(dsCreatedEvent.getEntity().getId()).isEqualTo(createDistributionSet.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Description("Verifies that the distribution set deleted event is published when a distribution set has been deleted")
|
||||||
|
public void distributionSetDeletedEventIsPublished() throws InterruptedException {
|
||||||
|
|
||||||
|
final DistributionSet generateDistributionSet = entityFactory.generateDistributionSet();
|
||||||
|
generateDistributionSet.setName("dsEventTest");
|
||||||
|
generateDistributionSet.setVersion("1");
|
||||||
|
final DistributionSet createDistributionSet = distributionSetManagement
|
||||||
|
.createDistributionSet(generateDistributionSet);
|
||||||
|
|
||||||
|
distributionSetManagement.deleteDistributionSet(createDistributionSet);
|
||||||
|
|
||||||
|
final DistributionDeletedEvent dsDeletedEvent = eventListener.waitForEvent(DistributionDeletedEvent.class, 1,
|
||||||
|
TimeUnit.SECONDS);
|
||||||
|
assertThat(dsDeletedEvent).isNotNull();
|
||||||
|
assertThat(dsDeletedEvent.getDistributionSetId()).isEqualTo(createDistributionSet.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyEventListener {
|
||||||
|
|
||||||
|
private final BlockingQueue<Event> queue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onEvent(final Event event) {
|
||||||
|
queue.offer(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T waitForEvent(final Class<T> eventType, final long timeout, final TimeUnit timeUnit)
|
||||||
|
throws InterruptedException {
|
||||||
|
Event event = null;
|
||||||
|
while ((event = queue.poll(timeout, timeUnit)) != null) {
|
||||||
|
if (event.getClass().isAssignableFrom(eventType)) {
|
||||||
|
return (T) event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assertions.fail("Missing event " + eventType + " within timeout " + timeout + " " + timeUnit);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,11 +9,24 @@
|
|||||||
package org.eclipse.hawkbit.rest.util;
|
package org.eclipse.hawkbit.rest.util;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.net.HttpHeaders.ACCEPT_RANGES;
|
||||||
|
import static com.google.common.net.HttpHeaders.CONTENT_DISPOSITION;
|
||||||
|
import static com.google.common.net.HttpHeaders.CONTENT_LENGTH;
|
||||||
|
import static com.google.common.net.HttpHeaders.CONTENT_RANGE;
|
||||||
|
import static com.google.common.net.HttpHeaders.ETAG;
|
||||||
|
import static com.google.common.net.HttpHeaders.IF_RANGE;
|
||||||
|
import static com.google.common.net.HttpHeaders.LAST_MODIFIED;
|
||||||
|
import static java.math.RoundingMode.DOWN;
|
||||||
|
import static javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;
|
||||||
|
import static org.eclipse.hawkbit.rest.util.ByteRange.MULTIPART_BOUNDARY;
|
||||||
|
import static org.springframework.http.HttpStatus.OK;
|
||||||
|
import static org.springframework.http.HttpStatus.PARTIAL_CONTENT;
|
||||||
|
import static org.springframework.http.HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE;
|
||||||
|
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.math.RoundingMode;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -27,23 +40,19 @@ import org.eclipse.hawkbit.repository.model.ActionStatus;
|
|||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.MediaType;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
import com.google.common.math.DoubleMath;
|
import com.google.common.math.DoubleMath;
|
||||||
import com.google.common.net.HttpHeaders;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for the Rest Source API.
|
* Utility class for the Rest Source API.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public final class RestResourceConversionHelper {
|
public final class RestResourceConversionHelper {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RestResourceConversionHelper.class);
|
private static final Logger LOG = LoggerFactory.getLogger(RestResourceConversionHelper.class);
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 4096;
|
private static final int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
// utility class, private constructor.
|
|
||||||
private RestResourceConversionHelper() {
|
private RestResourceConversionHelper() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -92,7 +101,8 @@ public final class RestResourceConversionHelper {
|
|||||||
*
|
*
|
||||||
* @return http code
|
* @return http code
|
||||||
*
|
*
|
||||||
* @see https://tools.ietf.org/html/rfc7233
|
* @see <a href="https://tools.ietf.org/html/rfc7233">https://tools.ietf.org
|
||||||
|
* /html/rfc7233</a>
|
||||||
*/
|
*/
|
||||||
public static ResponseEntity<InputStream> writeFileResponse(final LocalArtifact artifact,
|
public static ResponseEntity<InputStream> writeFileResponse(final LocalArtifact artifact,
|
||||||
final HttpServletResponse response, final HttpServletRequest request, final DbArtifact file,
|
final HttpServletResponse response, final HttpServletRequest request, final DbArtifact file,
|
||||||
@@ -107,11 +117,11 @@ public final class RestResourceConversionHelper {
|
|||||||
|
|
||||||
response.reset();
|
response.reset();
|
||||||
response.setBufferSize(BUFFER_SIZE);
|
response.setBufferSize(BUFFER_SIZE);
|
||||||
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + artifact.getFilename());
|
response.setHeader(CONTENT_DISPOSITION, "attachment;filename=" + artifact.getFilename());
|
||||||
response.setHeader(HttpHeaders.ETAG, etag);
|
response.setHeader(ETAG, etag);
|
||||||
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
|
response.setHeader(ACCEPT_RANGES, "bytes");
|
||||||
response.setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified);
|
response.setDateHeader(LAST_MODIFIED, lastModified);
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
response.setContentType(APPLICATION_OCTET_STREAM_VALUE);
|
||||||
|
|
||||||
final ByteRange full = new ByteRange(0, length - 1, length);
|
final ByteRange full = new ByteRange(0, length - 1, length);
|
||||||
final List<ByteRange> ranges = new ArrayList<>();
|
final List<ByteRange> ranges = new ArrayList<>();
|
||||||
@@ -123,9 +133,9 @@ public final class RestResourceConversionHelper {
|
|||||||
|
|
||||||
// Range header matches"bytes=n-n,n-n,n-n..."
|
// Range header matches"bytes=n-n,n-n,n-n..."
|
||||||
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
|
if (!range.matches("^bytes=\\d*-\\d*(,\\d*-\\d*)*$")) {
|
||||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length);
|
response.setHeader(CONTENT_RANGE, "bytes */" + length);
|
||||||
LOG.debug("range header for filename ({}) is not satisfiable: ", artifact.getFilename());
|
LOG.debug("range header for filename ({}) is not satisfiable: ", artifact.getFilename());
|
||||||
return new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
return new ResponseEntity<>(REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RFC: if the representation is unchanged, send me the part(s) that
|
// RFC: if the representation is unchanged, send me the part(s) that
|
||||||
@@ -144,32 +154,31 @@ public final class RestResourceConversionHelper {
|
|||||||
// full request - no range
|
// full request - no range
|
||||||
if (ranges.isEmpty() || ranges.get(0).equals(full)) {
|
if (ranges.isEmpty() || ranges.get(0).equals(full)) {
|
||||||
LOG.debug("filename ({}) results into a full request: ", artifact.getFilename());
|
LOG.debug("filename ({}) results into a full request: ", artifact.getFilename());
|
||||||
fullfileRequest(artifact, response, file, controllerManagement, statusId, full);
|
handleFullFileRequest(artifact, response, file, controllerManagement, statusId, full);
|
||||||
result = new ResponseEntity<>(HttpStatus.OK);
|
result = new ResponseEntity<>(OK);
|
||||||
}
|
}
|
||||||
// standard range request
|
// standard range request
|
||||||
else if (ranges.size() == 1) {
|
else if (ranges.size() == 1) {
|
||||||
LOG.debug("filename ({}) results into a standard range request: ", artifact.getFilename());
|
LOG.debug("filename ({}) results into a standard range request: ", artifact.getFilename());
|
||||||
standardRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
handleStandardRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
||||||
result = new ResponseEntity<>(HttpStatus.PARTIAL_CONTENT);
|
result = new ResponseEntity<>(PARTIAL_CONTENT);
|
||||||
}
|
}
|
||||||
// multipart range request
|
// multipart range request
|
||||||
else {
|
else {
|
||||||
LOG.debug("filename ({}) results into a multipart range request: ", artifact.getFilename());
|
LOG.debug("filename ({}) results into a multipart range request: ", artifact.getFilename());
|
||||||
multipartRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
handleMultipartRangeRequest(artifact, response, file, controllerManagement, statusId, ranges);
|
||||||
result = new ResponseEntity<>(HttpStatus.PARTIAL_CONTENT);
|
result = new ResponseEntity<>(PARTIAL_CONTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fullfileRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
private static void handleFullFileRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||||
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
||||||
final ByteRange full) {
|
final ByteRange full) {
|
||||||
final ByteRange r = full;
|
final ByteRange r = full;
|
||||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||||
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(r.getLength()));
|
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
||||||
@@ -182,7 +191,7 @@ public final class RestResourceConversionHelper {
|
|||||||
|
|
||||||
private static ResponseEntity<InputStream> extractRange(final HttpServletResponse response, final long length,
|
private static ResponseEntity<InputStream> extractRange(final HttpServletResponse response, final long length,
|
||||||
final List<ByteRange> ranges, final String range) {
|
final List<ByteRange> ranges, final String range) {
|
||||||
ResponseEntity<InputStream> result = null;
|
|
||||||
if (ranges.isEmpty()) {
|
if (ranges.isEmpty()) {
|
||||||
for (final String part : range.substring(6).split(",")) {
|
for (final String part : range.substring(6).split(",")) {
|
||||||
long start = sublong(part, 0, part.indexOf('-'));
|
long start = sublong(part, 0, part.indexOf('-'));
|
||||||
@@ -198,9 +207,8 @@ public final class RestResourceConversionHelper {
|
|||||||
// Check if Range is syntactically valid. If not, then return
|
// Check if Range is syntactically valid. If not, then return
|
||||||
// 416.
|
// 416.
|
||||||
if (start > end) {
|
if (start > end) {
|
||||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + length);
|
response.setHeader(CONTENT_RANGE, "bytes */" + length);
|
||||||
result = new ResponseEntity<>(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
|
return new ResponseEntity<>(REQUESTED_RANGE_NOT_SATISFIABLE);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add range.
|
// Add range.
|
||||||
@@ -218,10 +226,10 @@ public final class RestResourceConversionHelper {
|
|||||||
|
|
||||||
private static void checkForShortcut(final HttpServletRequest request, final String etag, final long lastModified,
|
private static void checkForShortcut(final HttpServletRequest request, final String etag, final long lastModified,
|
||||||
final ByteRange full, final List<ByteRange> ranges) {
|
final ByteRange full, final List<ByteRange> ranges) {
|
||||||
final String ifRange = request.getHeader(HttpHeaders.IF_RANGE);
|
final String ifRange = request.getHeader(IF_RANGE);
|
||||||
if (ifRange != null && !ifRange.equals(etag)) {
|
if (ifRange != null && !ifRange.equals(etag)) {
|
||||||
try {
|
try {
|
||||||
final long ifRangeTime = request.getDateHeader(HttpHeaders.IF_RANGE);
|
final long ifRangeTime = request.getDateHeader(IF_RANGE);
|
||||||
if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) {
|
if (ifRangeTime != -1 && ifRangeTime + 1000 < lastModified) {
|
||||||
ranges.add(full);
|
ranges.add(full);
|
||||||
}
|
}
|
||||||
@@ -232,17 +240,17 @@ public final class RestResourceConversionHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void multipartRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
private static void handleMultipartRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||||
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
||||||
final List<ByteRange> ranges) {
|
final List<ByteRange> ranges) {
|
||||||
response.setContentType("multipart/byteranges; boundary=" + ByteRange.MULTIPART_BOUNDARY);
|
response.setContentType("multipart/byteranges; boundary=" + MULTIPART_BOUNDARY);
|
||||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
response.setStatus(SC_PARTIAL_CONTENT);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (final ByteRange r : ranges) {
|
for (final ByteRange r : ranges) {
|
||||||
// Add multipart boundary and header fields for every range.
|
// Add multipart boundary and header fields for every range.
|
||||||
response.getOutputStream().println();
|
response.getOutputStream().println();
|
||||||
response.getOutputStream().println("--" + ByteRange.MULTIPART_BOUNDARY);
|
response.getOutputStream().println("--" + MULTIPART_BOUNDARY);
|
||||||
response.getOutputStream()
|
response.getOutputStream()
|
||||||
.println("Content-Range: bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
.println("Content-Range: bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||||
|
|
||||||
@@ -253,20 +261,20 @@ public final class RestResourceConversionHelper {
|
|||||||
|
|
||||||
// End with final multipart boundary.
|
// End with final multipart boundary.
|
||||||
response.getOutputStream().println();
|
response.getOutputStream().println();
|
||||||
response.getOutputStream().print("--" + ByteRange.MULTIPART_BOUNDARY + "--");
|
response.getOutputStream().print("--" + MULTIPART_BOUNDARY + "--");
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
LOG.error("multipartRangeRequest of file ({}) failed!", artifact.getFilename(), e);
|
LOG.error("multipartRangeRequest of file ({}) failed!", artifact.getFilename(), e);
|
||||||
throw new FileSteamingFailedException(artifact.getFilename());
|
throw new FileSteamingFailedException(artifact.getFilename());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void standardRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
private static void handleStandardRangeRequest(final LocalArtifact artifact, final HttpServletResponse response,
|
||||||
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
final DbArtifact file, final ControllerManagement controllerManagement, final Long statusId,
|
||||||
final List<ByteRange> ranges) {
|
final List<ByteRange> ranges) {
|
||||||
final ByteRange r = ranges.get(0);
|
final ByteRange r = ranges.get(0);
|
||||||
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
response.setHeader(CONTENT_RANGE, "bytes " + r.getStart() + "-" + r.getEnd() + "/" + r.getTotal());
|
||||||
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(r.getLength()));
|
response.setHeader(CONTENT_LENGTH, String.valueOf(r.getLength()));
|
||||||
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
response.setStatus(SC_PARTIAL_CONTENT);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
copyStreams(file.getFileInputStream(), response.getOutputStream(), controllerManagement, statusId,
|
||||||
@@ -315,7 +323,7 @@ public final class RestResourceConversionHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (controllerManagement != null) {
|
if (controllerManagement != null) {
|
||||||
final int newPercent = DoubleMath.roundToInt(total * 100.0 / length, RoundingMode.DOWN);
|
final int newPercent = DoubleMath.roundToInt(total * 100.0 / length, DOWN);
|
||||||
|
|
||||||
// every 10 percent an event
|
// every 10 percent an event
|
||||||
if (newPercent == 100 || newPercent > progressPercent + 10) {
|
if (newPercent == 100 || newPercent > progressPercent + 10) {
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ public class DosFilter extends OncePerRequestFilter {
|
|||||||
|
|
||||||
boolean processChain;
|
boolean processChain;
|
||||||
|
|
||||||
final String ip = IpUtil.getClientIpFromRequest(request, forwardHeader, true).getHost();
|
final String ip = IpUtil.getClientIpFromRequest(request, forwardHeader).getHost();
|
||||||
|
|
||||||
if (checkIpFails(ip)) {
|
if (checkIpFails(ip)) {
|
||||||
processChain = handleMissingIpAddress(response);
|
processChain = handleMissingIpAddress(response);
|
||||||
} else {
|
} else {
|
||||||
@@ -121,7 +122,6 @@ public class DosFilter extends OncePerRequestFilter {
|
|||||||
if (processChain) {
|
if (processChain) {
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public final class IpUtil {
|
|||||||
* {@link HttpServletRequest} by either the
|
* {@link HttpServletRequest} by either the
|
||||||
* {@link HttpHeaders#X_FORWARDED_FOR} or by the
|
* {@link HttpHeaders#X_FORWARDED_FOR} or by the
|
||||||
* {@link HttpServletRequest#getRemoteAddr()} methods.
|
* {@link HttpServletRequest#getRemoteAddr()} methods.
|
||||||
*
|
*
|
||||||
* @param request
|
* @param request
|
||||||
* the {@link HttpServletRequest} to determine the IP address
|
* the {@link HttpServletRequest} to determine the IP address
|
||||||
* where this request has been sent from
|
* where this request has been sent from
|
||||||
@@ -65,21 +65,23 @@ public final class IpUtil {
|
|||||||
* {@link HttpServletRequest} by either the
|
* {@link HttpServletRequest} by either the
|
||||||
* {@link HttpHeaders#X_FORWARDED_FOR} or by the
|
* {@link HttpHeaders#X_FORWARDED_FOR} or by the
|
||||||
* {@link HttpServletRequest#getRemoteAddr()} methods.
|
* {@link HttpServletRequest#getRemoteAddr()} methods.
|
||||||
*
|
*
|
||||||
* @param request
|
* @param request
|
||||||
* the {@link HttpServletRequest} to determine the IP address
|
* the {@link HttpServletRequest} to determine the IP address
|
||||||
* where this request has been sent from
|
* where this request has been sent from
|
||||||
* @param forwardHeader
|
* @param forwardHeader
|
||||||
* the header name containing the IP address e.g. forwarded by a
|
* the header name containing the IP address e.g. forwarded by a
|
||||||
* proxy {@code x-forwarded-for}
|
* proxy {@code x-forwarded-for}
|
||||||
*
|
|
||||||
* @param trackRemoteIp
|
|
||||||
* to <code>true</code> if remote IP should be tracked.
|
|
||||||
* @return the {@link URI} based IP address from the client which sent the
|
* @return the {@link URI} based IP address from the client which sent the
|
||||||
* request
|
* request
|
||||||
*/
|
*/
|
||||||
public static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader,
|
public static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader) {
|
||||||
|
return getClientIpFromRequest(request, forwardHeader, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static URI getClientIpFromRequest(final HttpServletRequest request, final String forwardHeader,
|
||||||
final boolean trackRemoteIp) {
|
final boolean trackRemoteIp) {
|
||||||
|
|
||||||
String ip;
|
String ip;
|
||||||
|
|
||||||
if (trackRemoteIp) {
|
if (trackRemoteIp) {
|
||||||
@@ -113,7 +115,7 @@ public final class IpUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link URI} with scheme and host.
|
* Create a {@link URI} with scheme and host.
|
||||||
*
|
*
|
||||||
* @param scheme
|
* @param scheme
|
||||||
* the scheme
|
* the scheme
|
||||||
* @param host
|
* @param host
|
||||||
@@ -132,7 +134,7 @@ public final class IpUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link URI} with amqp scheme and host.
|
* Create a {@link URI} with amqp scheme and host.
|
||||||
*
|
*
|
||||||
* @param host
|
* @param host
|
||||||
* the host
|
* the host
|
||||||
* @param exchange
|
* @param exchange
|
||||||
@@ -147,7 +149,7 @@ public final class IpUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a {@link URI} with http scheme and host.
|
* Create a {@link URI} with http scheme and host.
|
||||||
*
|
*
|
||||||
* @param host
|
* @param host
|
||||||
* the host
|
* the host
|
||||||
* @return the {@link URI}
|
* @return the {@link URI}
|
||||||
@@ -160,7 +162,7 @@ public final class IpUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if scheme contains http and uri ist not <code>null</code>.
|
* Check if scheme contains http and uri ist not <code>null</code>.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param uri
|
||||||
* the uri
|
* the uri
|
||||||
* @return true = is http host false = not
|
* @return true = is http host false = not
|
||||||
@@ -171,7 +173,7 @@ public final class IpUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if host scheme amqp and uri ist not <code>null</code>.
|
* Check if host scheme amqp and uri ist not <code>null</code>.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param uri
|
||||||
* the uri
|
* the uri
|
||||||
* @return true = is http host false = not
|
* @return true = is http host false = not
|
||||||
@@ -183,7 +185,7 @@ public final class IpUtil {
|
|||||||
/**
|
/**
|
||||||
* Check if the IP address of that {@link URI} is known, i.e. not an AQMP
|
* Check if the IP address of that {@link URI} is known, i.e. not an AQMP
|
||||||
* exchange in DMF case and not HIDDEN_IP in DDI case.
|
* exchange in DMF case and not HIDDEN_IP in DDI case.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param uri
|
||||||
* the uri
|
* the uri
|
||||||
* @return <code>true</code> if IP address is actually known by the server
|
* @return <code>true</code> if IP address is actually known by the server
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.util;
|
package org.eclipse.hawkbit.util;
|
||||||
|
|
||||||
|
import static com.google.common.net.HttpHeaders.X_FORWARDED_FOR;
|
||||||
import static org.fest.assertions.api.Assertions.assertThat;
|
import static org.fest.assertions.api.Assertions.assertThat;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -21,13 +22,13 @@ import java.net.URI;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||||
|
import org.eclipse.hawkbit.security.HawkbitSecurityProperties.Clients;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
import com.google.common.net.HttpHeaders;
|
|
||||||
|
|
||||||
import ru.yandex.qatools.allure.annotations.Description;
|
import ru.yandex.qatools.allure.annotations.Description;
|
||||||
import ru.yandex.qatools.allure.annotations.Features;
|
import ru.yandex.qatools.allure.annotations.Features;
|
||||||
import ru.yandex.qatools.allure.annotations.Stories;
|
import ru.yandex.qatools.allure.annotations.Stories;
|
||||||
@@ -37,69 +38,73 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
|||||||
@Stories("IP Util Test")
|
@Stories("IP Util Test")
|
||||||
public class IpUtilTest {
|
public class IpUtilTest {
|
||||||
|
|
||||||
|
private static final String KNOWN_REQUEST_HEADER = "bumlux";
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private HttpServletRequest requestMock;
|
private HttpServletRequest requestMock;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Clients clientMock;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private HawkbitSecurityProperties securityPropertyMock;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests create uri from request")
|
@Description("Tests create uri from request")
|
||||||
public void getRemoteAddrFromRequestIfForwaredHeaderNotPresent() {
|
public void getRemoteAddrFromRequestIfForwaredHeaderNotPresent() {
|
||||||
// known values
|
|
||||||
final URI knownRemoteClientIP = IpUtil.createHttpUri("127.0.0.1");
|
final URI knownRemoteClientIP = IpUtil.createHttpUri("127.0.0.1");
|
||||||
// mock
|
when(requestMock.getHeader(X_FORWARDED_FOR)).thenReturn(null);
|
||||||
when(requestMock.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn(null);
|
|
||||||
when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost());
|
when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost());
|
||||||
|
|
||||||
// test
|
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, KNOWN_REQUEST_HEADER);
|
||||||
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux", true);
|
|
||||||
|
|
||||||
// verify
|
// verify
|
||||||
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
||||||
.isEqualTo(knownRemoteClientIP);
|
.isEqualTo(knownRemoteClientIP);
|
||||||
verify(requestMock, times(1)).getHeader("bumlux");
|
verify(requestMock, times(1)).getHeader(KNOWN_REQUEST_HEADER);
|
||||||
verify(requestMock, times(1)).getRemoteAddr();
|
verify(requestMock, times(1)).getRemoteAddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests create uri from request with masked IP when IP tracking is disabled")
|
@Description("Tests create uri from request with masked IP when IP tracking is disabled")
|
||||||
public void maskRemoteAddrIfDisabled() {
|
public void maskRemoteAddrIfDisabled() {
|
||||||
// known values
|
|
||||||
final URI knownRemoteClientIP = IpUtil.createHttpUri("***");
|
final URI knownRemoteClientIP = IpUtil.createHttpUri("***");
|
||||||
// mock
|
when(requestMock.getHeader(X_FORWARDED_FOR)).thenReturn(null);
|
||||||
when(requestMock.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn(null);
|
|
||||||
when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost());
|
when(requestMock.getRemoteAddr()).thenReturn(knownRemoteClientIP.getHost());
|
||||||
|
when(securityPropertyMock.getClients()).thenReturn(clientMock);
|
||||||
|
when(clientMock.getRemoteIpHeader()).thenReturn(KNOWN_REQUEST_HEADER);
|
||||||
|
when(clientMock.isTrackRemoteIp()).thenReturn(false);
|
||||||
|
|
||||||
// test
|
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, securityPropertyMock);
|
||||||
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "bumlux", false);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
||||||
.isEqualTo(knownRemoteClientIP);
|
.isEqualTo(knownRemoteClientIP);
|
||||||
verify(requestMock, times(0)).getHeader("bumlux");
|
verify(requestMock, times(0)).getHeader(KNOWN_REQUEST_HEADER);
|
||||||
verify(requestMock, times(0)).getRemoteAddr();
|
verify(requestMock, times(0)).getRemoteAddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests create uri from x forward header")
|
@Description("Tests create uri from x forward header")
|
||||||
public void getRemoteAddrFromXForwardedForHeader() {
|
public void getRemoteAddrFromXForwardedForHeader() {
|
||||||
// known values
|
|
||||||
final URI knownRemoteClientIP = IpUtil.createHttpUri("10.99.99.1");
|
final URI knownRemoteClientIP = IpUtil.createHttpUri("10.99.99.1");
|
||||||
// mock
|
when(requestMock.getHeader(X_FORWARDED_FOR)).thenReturn(knownRemoteClientIP.getHost());
|
||||||
when(requestMock.getHeader(HttpHeaders.X_FORWARDED_FOR)).thenReturn(knownRemoteClientIP.getHost());
|
|
||||||
when(requestMock.getRemoteAddr()).thenReturn(null);
|
when(requestMock.getRemoteAddr()).thenReturn(null);
|
||||||
|
|
||||||
// test
|
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For");
|
||||||
final URI remoteAddr = IpUtil.getClientIpFromRequest(requestMock, "X-Forwarded-For", true);
|
|
||||||
|
|
||||||
// verify
|
|
||||||
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
assertThat(remoteAddr).as("The remote address should be as the known client IP address")
|
||||||
.isEqualTo(knownRemoteClientIP);
|
.isEqualTo(knownRemoteClientIP);
|
||||||
verify(requestMock, times(1)).getHeader(HttpHeaders.X_FORWARDED_FOR);
|
verify(requestMock, times(1)).getHeader(X_FORWARDED_FOR);
|
||||||
verify(requestMock, times(0)).getRemoteAddr();
|
verify(requestMock, times(0)).getRemoteAddr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests create http uri ipv4 and ipv6")
|
@Description("Tests create http uri ipv4 and ipv6")
|
||||||
public void testCreateHttpUri() {
|
public void testCreateHttpUri() {
|
||||||
|
|
||||||
final String ipv4 = "10.99.99.1";
|
final String ipv4 = "10.99.99.1";
|
||||||
URI httpUri = IpUtil.createHttpUri(ipv4);
|
URI httpUri = IpUtil.createHttpUri(ipv4);
|
||||||
assertHttpUri(ipv4, httpUri);
|
assertHttpUri(ipv4, httpUri);
|
||||||
@@ -111,7 +116,6 @@ public class IpUtilTest {
|
|||||||
final String ipv6 = "0:0:0:0:0:0:0:1";
|
final String ipv6 = "0:0:0:0:0:0:0:1";
|
||||||
httpUri = IpUtil.createHttpUri(ipv6);
|
httpUri = IpUtil.createHttpUri(ipv6);
|
||||||
assertHttpUri("[" + ipv6 + "]", httpUri);
|
assertHttpUri("[" + ipv6 + "]", httpUri);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertHttpUri(final String host, final URI httpUri) {
|
private void assertHttpUri(final String host, final URI httpUri) {
|
||||||
@@ -124,6 +128,7 @@ public class IpUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests create amqp uri ipv4 and ipv6")
|
@Description("Tests create amqp uri ipv4 and ipv6")
|
||||||
public void testCreateAmqpUri() {
|
public void testCreateAmqpUri() {
|
||||||
|
|
||||||
final String ipv4 = "10.99.99.1";
|
final String ipv4 = "10.99.99.1";
|
||||||
URI amqpUri = IpUtil.createAmqpUri(ipv4, "path");
|
URI amqpUri = IpUtil.createAmqpUri(ipv4, "path");
|
||||||
assertAmqpUri(ipv4, amqpUri);
|
assertAmqpUri(ipv4, amqpUri);
|
||||||
@@ -138,6 +143,7 @@ public class IpUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertAmqpUri(final String host, final URI amqpUri) {
|
private void assertAmqpUri(final String host, final URI amqpUri) {
|
||||||
|
|
||||||
assertTrue("The given URI is an AMQP scheme", IpUtil.isAmqpUri(amqpUri));
|
assertTrue("The given URI is an AMQP scheme", IpUtil.isAmqpUri(amqpUri));
|
||||||
assertFalse("The given URI is not an HTTP scheme", IpUtil.isHttpUri(amqpUri));
|
assertFalse("The given URI is not an HTTP scheme", IpUtil.isHttpUri(amqpUri));
|
||||||
assertEquals("The given host matches the URI host", host, amqpUri.getHost());
|
assertEquals("The given host matches the URI host", host, amqpUri.getHost());
|
||||||
@@ -148,17 +154,19 @@ public class IpUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
@Description("Tests create invalid uri")
|
@Description("Tests create invalid uri")
|
||||||
public void testCreateInvalidUri() {
|
public void testCreateInvalidUri() {
|
||||||
|
|
||||||
final String host = "10.99.99.1";
|
final String host = "10.99.99.1";
|
||||||
final URI testUri = IpUtil.createUri("test", host);
|
final URI testUri = IpUtil.createUri("test", host);
|
||||||
|
|
||||||
assertFalse("The given URI is not an AMQP address", IpUtil.isAmqpUri(testUri));
|
assertFalse("The given URI is not an AMQP address", IpUtil.isAmqpUri(testUri));
|
||||||
assertFalse("The given URI is not an HTTP address", IpUtil.isHttpUri(testUri));
|
assertFalse("The given URI is not an HTTP address", IpUtil.isHttpUri(testUri));
|
||||||
assertEquals("The given host matches the URI host", host, testUri.getHost());
|
assertEquals("The given host matches the URI host", host, testUri.getHost());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IpUtil.createUri(":/", host);
|
IpUtil.createUri(":/", host);
|
||||||
fail("Missing expected IllegalArgumentException due invalid URI");
|
fail("Missing expected IllegalArgumentException due invalid URI");
|
||||||
} catch (final IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
// expected
|
// expected
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,25 +12,29 @@ import java.util.HashSet;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.eventbus.event.Event;
|
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||||
import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagCreatedBulkEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagCreatedBulkEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagDeletedEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagDeletedEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagUpdateEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetTagUpdateEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutChangeEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.RolloutChangeEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupChangeEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupChangeEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetDeletedEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetInfoUpdateEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagCreatedBulkEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagCreatedBulkEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagDeletedEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagDeletedEvent;
|
||||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagUpdateEvent;
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetTagUpdateEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default hawkbit event provider.
|
* The default hawkbit event provider.
|
||||||
*/
|
*/
|
||||||
public class HawkbitEventProvider implements UIEventProvider {
|
public class HawkbitEventProvider implements UIEventProvider {
|
||||||
|
|
||||||
private static final Set<Class<? extends Event>> SINGLE_EVENTS = new HashSet<>(6);
|
private static final Set<Class<? extends Event>> SINGLE_EVENTS = new HashSet<>(9);
|
||||||
private static final Set<Class<? extends Event>> BULK_EVENTS = new HashSet<>(3);
|
private static final Set<Class<? extends Event>> BULK_EVENTS = new HashSet<>(5);
|
||||||
|
|
||||||
static {
|
static {
|
||||||
SINGLE_EVENTS.add(TargetTagCreatedBulkEvent.class);
|
SINGLE_EVENTS.add(TargetTagCreatedBulkEvent.class);
|
||||||
@@ -41,10 +45,14 @@ public class HawkbitEventProvider implements UIEventProvider {
|
|||||||
SINGLE_EVENTS.add(RolloutGroupChangeEvent.class);
|
SINGLE_EVENTS.add(RolloutGroupChangeEvent.class);
|
||||||
SINGLE_EVENTS.add(RolloutChangeEvent.class);
|
SINGLE_EVENTS.add(RolloutChangeEvent.class);
|
||||||
SINGLE_EVENTS.add(TargetTagUpdateEvent.class);
|
SINGLE_EVENTS.add(TargetTagUpdateEvent.class);
|
||||||
|
SINGLE_EVENTS.add(DistributionSetUpdateEvent.class);
|
||||||
|
|
||||||
BULK_EVENTS.add(TargetCreatedEvent.class);
|
BULK_EVENTS.add(TargetCreatedEvent.class);
|
||||||
BULK_EVENTS.add(TargetInfoUpdateEvent.class);
|
BULK_EVENTS.add(TargetInfoUpdateEvent.class);
|
||||||
BULK_EVENTS.add(TargetDeletedEvent.class);
|
BULK_EVENTS.add(TargetDeletedEvent.class);
|
||||||
|
BULK_EVENTS.add(DistributionDeletedEvent.class);
|
||||||
|
BULK_EVENTS.add(DistributionCreatedEvent.class);
|
||||||
|
BULK_EVENTS.add(TargetUpdatedEvent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.artifacts.details;
|
package org.eclipse.hawkbit.ui.artifacts.details;
|
||||||
|
|
||||||
|
import static org.apache.commons.lang3.ArrayUtils.isEmpty;
|
||||||
|
import static org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil.isNotNullOrEmpty;
|
||||||
|
import static org.springframework.data.domain.Sort.Direction.ASC;
|
||||||
|
import static org.springframework.data.domain.Sort.Direction.DESC;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -15,7 +20,6 @@ import org.eclipse.hawkbit.repository.ArtifactManagement;
|
|||||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||||
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -39,7 +43,7 @@ public class ArtifactBeanQuery extends AbstractBeanQuery<LocalArtifact> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parametric Constructor.
|
* Parametric Constructor.
|
||||||
*
|
*
|
||||||
* @param definition
|
* @param definition
|
||||||
* as Def
|
* as Def
|
||||||
* @param queryConfig
|
* @param queryConfig
|
||||||
@@ -51,18 +55,18 @@ public class ArtifactBeanQuery extends AbstractBeanQuery<LocalArtifact> {
|
|||||||
*/
|
*/
|
||||||
public ArtifactBeanQuery(final QueryDefinition definition, final Map<String, Object> queryConfig,
|
public ArtifactBeanQuery(final QueryDefinition definition, final Map<String, Object> queryConfig,
|
||||||
final Object[] sortIds, final boolean[] sortStates) {
|
final Object[] sortIds, final boolean[] sortStates) {
|
||||||
|
|
||||||
super(definition, queryConfig, sortIds, sortStates);
|
super(definition, queryConfig, sortIds, sortStates);
|
||||||
|
|
||||||
if (HawkbitCommonUtil.mapCheckStrKey(queryConfig)) {
|
if (isNotNullOrEmpty(queryConfig)) {
|
||||||
baseSwModuleId = (Long) queryConfig.get(SPUIDefinitions.BY_BASE_SOFTWARE_MODULE);
|
baseSwModuleId = (Long) queryConfig.get(SPUIDefinitions.BY_BASE_SOFTWARE_MODULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HawkbitCommonUtil.checkBolArray(sortStates)) {
|
if (!isEmpty(sortStates)) {
|
||||||
// Initalize Sor
|
sort = new Sort(sortStates[0] ? ASC : DESC, (String) sortIds[0]);
|
||||||
sort = new Sort(sortStates[0] ? Direction.ASC : Direction.DESC, (String) sortIds[0]);
|
|
||||||
// Add sort.
|
|
||||||
for (int targetId = 1; targetId < sortIds.length; targetId++) {
|
for (int targetId = 1; targetId < sortIds.length; targetId++) {
|
||||||
sort.and(new Sort(sortStates[targetId] ? Direction.ASC : Direction.DESC, (String) sortIds[targetId]));
|
sort.and(new Sort(sortStates[targetId] ? ASC : DESC, (String) sortIds[targetId]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
|||||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
|
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
||||||
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
|
import org.eclipse.hawkbit.ui.common.ConfirmationDialog;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
@@ -149,8 +150,8 @@ public class ArtifactDetailsLayout extends VerticalLayout {
|
|||||||
final SoftwareModule softwareModule = artifactUploadState.getSelectedBaseSoftwareModule().get();
|
final SoftwareModule softwareModule = artifactUploadState.getSelectedBaseSoftwareModule().get();
|
||||||
labelStr = HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion());
|
labelStr = HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion());
|
||||||
}
|
}
|
||||||
titleOfArtifactDetails = SPUIComponentProvider.getLabel(
|
titleOfArtifactDetails = new LabelBuilder().name(HawkbitCommonUtil.getArtifactoryDetailsLabelId(labelStr))
|
||||||
HawkbitCommonUtil.getArtifactoryDetailsLabelId(labelStr), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
.buildCaptionLabel();
|
||||||
titleOfArtifactDetails.setContentMode(ContentMode.HTML);
|
titleOfArtifactDetails.setContentMode(ContentMode.HTML);
|
||||||
titleOfArtifactDetails.setSizeFull();
|
titleOfArtifactDetails.setSizeFull();
|
||||||
titleOfArtifactDetails.setImmediate(true);
|
titleOfArtifactDetails.setImmediate(true);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.artifacts.event;
|
package org.eclipse.hawkbit.ui.artifacts.event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Holds the upload file status.
|
* Holds the upload file status.
|
||||||
@@ -14,24 +15,36 @@ package org.eclipse.hawkbit.ui.artifacts.event;
|
|||||||
*/
|
*/
|
||||||
public class UploadStatusEvent {
|
public class UploadStatusEvent {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event type definition of events during the artifact upload life-cycle
|
||||||
|
* from receiving the upload until the process end.
|
||||||
|
*/
|
||||||
public enum UploadStatusEventType {
|
public enum UploadStatusEventType {
|
||||||
UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED, ABORT_UPLOAD
|
RECEIVE_UPLOAD, UPLOAD_FAILED, UPLOAD_IN_PROGRESS, UPLOAD_STARTED, UPLOAD_FINISHED, UPLOAD_SUCCESSFUL, UPLOAD_STREAMING_FAILED, UPLOAD_STREAMING_FINISHED, ABORT_UPLOAD
|
||||||
}
|
}
|
||||||
|
|
||||||
private UploadStatusEventType uploadProgressEventType;
|
private final UploadStatusEventType uploadProgressEventType;
|
||||||
|
|
||||||
private UploadFileStatus uploadStatus;
|
private UploadFileStatus uploadStatus;
|
||||||
|
|
||||||
public UploadStatusEvent(UploadStatusEventType eventType, UploadFileStatus entity) {
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param eventType
|
||||||
|
* the type of the event
|
||||||
|
* @param uploadStatus
|
||||||
|
* the upload status of this event
|
||||||
|
*/
|
||||||
|
public UploadStatusEvent(final UploadStatusEventType eventType, final UploadFileStatus uploadStatus) {
|
||||||
this.uploadProgressEventType = eventType;
|
this.uploadProgressEventType = eventType;
|
||||||
this.uploadStatus = entity;
|
this.uploadStatus = uploadStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UploadFileStatus getUploadStatus() {
|
public UploadFileStatus getUploadStatus() {
|
||||||
return uploadStatus;
|
return uploadStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUploadStatus(UploadFileStatus uploadStatus) {
|
public void setUploadStatus(final UploadFileStatus uploadStatus) {
|
||||||
this.uploadStatus = uploadStatus;
|
this.uploadStatus = uploadStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class BaseSwModuleBeanQuery extends AbstractBeanQuery<ProxyBaseSoftwareMo
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parametric Constructor.
|
* Parametric Constructor.
|
||||||
*
|
*
|
||||||
* @param definition
|
* @param definition
|
||||||
* as Def
|
* as Def
|
||||||
* @param queryConfig
|
* @param queryConfig
|
||||||
@@ -56,7 +56,7 @@ public class BaseSwModuleBeanQuery extends AbstractBeanQuery<ProxyBaseSoftwareMo
|
|||||||
public BaseSwModuleBeanQuery(final QueryDefinition definition, final Map<String, Object> queryConfig,
|
public BaseSwModuleBeanQuery(final QueryDefinition definition, final Map<String, Object> queryConfig,
|
||||||
final Object[] sortIds, final boolean[] sortStates) {
|
final Object[] sortIds, final boolean[] sortStates) {
|
||||||
super(definition, queryConfig, sortIds, sortStates);
|
super(definition, queryConfig, sortIds, sortStates);
|
||||||
if (HawkbitCommonUtil.mapCheckStrKey(queryConfig)) {
|
if (HawkbitCommonUtil.isNotNullOrEmpty(queryConfig)) {
|
||||||
type = (SoftwareModuleType) queryConfig.get(SPUIDefinitions.BY_SOFTWARE_MODULE_TYPE);
|
type = (SoftwareModuleType) queryConfig.get(SPUIDefinitions.BY_SOFTWARE_MODULE_TYPE);
|
||||||
searchText = (String) queryConfig.get(SPUIDefinitions.FILTER_BY_TEXT);
|
searchText = (String) queryConfig.get(SPUIDefinitions.FILTER_BY_TEXT);
|
||||||
if (!Strings.isNullOrEmpty(searchText)) {
|
if (!Strings.isNullOrEmpty(searchText)) {
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
|||||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
||||||
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
|
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
|
||||||
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
|
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
|
||||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
|
||||||
@@ -118,26 +120,17 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createRequiredComponents() {
|
private void createRequiredComponents() {
|
||||||
/* name textfield */
|
|
||||||
nameTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "", ValoTheme.TEXTFIELD_TINY,
|
|
||||||
true, null, i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
nameTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_NAME);
|
|
||||||
|
|
||||||
/* version text field */
|
nameTextField = createTextField("textfield.name", SPUIComponentIdProvider.SOFT_MODULE_NAME);
|
||||||
versionTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.version"), "",
|
|
||||||
ValoTheme.TEXTFIELD_TINY, true, null, i18n.get("textfield.version"), true,
|
|
||||||
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
versionTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_VERSION);
|
|
||||||
|
|
||||||
/* Vendor text field */
|
versionTextField = createTextField("textfield.version", SPUIComponentIdProvider.SOFT_MODULE_VERSION);
|
||||||
vendorTextField = SPUIComponentProvider.getTextField(i18n.get("textfield.vendor"), "", ValoTheme.TEXTFIELD_TINY,
|
|
||||||
false, null, i18n.get("textfield.vendor"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
vendorTextField.setId(SPUIComponentIdProvider.SOFT_MODULE_VENDOR);
|
|
||||||
|
|
||||||
descTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "text-area-style",
|
vendorTextField = createTextField("textfield.vendor", SPUIComponentIdProvider.SOFT_MODULE_VENDOR);
|
||||||
ValoTheme.TEXTAREA_TINY, false, null, i18n.get("textfield.description"),
|
vendorTextField.setRequired(false);
|
||||||
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
|
|
||||||
descTextArea.setId(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION);
|
descTextArea = new TextAreaBuilder().caption(i18n.get("textfield.description")).style("text-area-style")
|
||||||
|
.prompt(i18n.get("textfield.description")).id(SPUIComponentIdProvider.ADD_SW_MODULE_DESCRIPTION)
|
||||||
|
.buildTextComponent();
|
||||||
|
|
||||||
typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true,
|
typeComboBox = SPUIComponentProvider.getComboBox(i18n.get("upload.swmodule.type"), "", "", null, null, true,
|
||||||
null, i18n.get("upload.swmodule.type"));
|
null, i18n.get("upload.swmodule.type"));
|
||||||
@@ -148,6 +141,11 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
|
|||||||
populateTypeNameCombo();
|
populateTypeNameCombo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TextField createTextField(final String in18Key, final String id) {
|
||||||
|
return new TextFieldBuilder().caption(i18n.get(in18Key)).required(true).prompt(i18n.get(in18Key))
|
||||||
|
.immediate(true).id(id).buildTextComponent();
|
||||||
|
}
|
||||||
|
|
||||||
private void populateTypeNameCombo() {
|
private void populateTypeNameCombo() {
|
||||||
typeComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer(
|
typeComboBox.setContainerDataSource(HawkbitCommonUtil.createLazyQueryContainer(
|
||||||
new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class)));
|
new BeanQueryFactory<SoftwareModuleTypeBeanQuery>(SoftwareModuleTypeBeanQuery.class)));
|
||||||
@@ -181,8 +179,11 @@ public class SoftwareModuleAddUpdateWindow extends CustomComponent implements Se
|
|||||||
|
|
||||||
setCompositionRoot(formLayout);
|
setCompositionRoot(formLayout);
|
||||||
|
|
||||||
window = SPUIWindowDecorator.getWindow(i18n.get("upload.caption.add.new.swmodule"), null,
|
window = new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW)
|
||||||
SPUIDefinitions.CREATE_UPDATE_WINDOW, this, event -> saveOrUpdate(), null, null, formLayout, i18n);
|
.caption(i18n.get("upload.caption.add.new.swmodule")).content(this)
|
||||||
|
.saveButtonClickListener(event -> saveOrUpdate()).layout(formLayout).i18n(i18n)
|
||||||
|
.buildCommonDialogWindow();
|
||||||
|
|
||||||
window.getButtonsLayout().removeStyleName("actionButtonsMargin");
|
window.getButtonsLayout().removeStyleName("actionButtonsMargin");
|
||||||
|
|
||||||
nameTextField.setEnabled(!editSwModule);
|
nameTextField.setEnabled(!editSwModule);
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ import com.vaadin.ui.UI;
|
|||||||
/**
|
/**
|
||||||
* Header of Software module table.
|
* Header of Software module table.
|
||||||
*/
|
*/
|
||||||
@SpringComponent
|
|
||||||
@ViewScope
|
@ViewScope
|
||||||
|
@SpringComponent
|
||||||
public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModule, Long> {
|
public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModule, Long> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 6469417305487144809L;
|
private static final long serialVersionUID = 6469417305487144809L;
|
||||||
@@ -161,7 +161,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
|||||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||||
void onEvent(final UploadArtifactUIEvent event) {
|
void onEvent(final UploadArtifactUIEvent event) {
|
||||||
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) {
|
if (event == UploadArtifactUIEvent.DELETED_ALL_SOFWARE) {
|
||||||
UI.getCurrent().access(() -> refreshFilter());
|
UI.getCurrent().access(this::refreshFilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
|||||||
public Object generateCell(final Table source, final Object itemId, final Object columnId) {
|
public Object generateCell(final Table source, final Object itemId, final Object columnId) {
|
||||||
final String nameVersionStr = getNameAndVerion(itemId);
|
final String nameVersionStr = getNameAndVerion(itemId);
|
||||||
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
|
final Button manageMetaDataBtn = createManageMetadataButton(nameVersionStr);
|
||||||
manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId, nameVersionStr));
|
manageMetaDataBtn.addClickListener(event -> showMetadataDetails((Long) itemId));
|
||||||
return manageMetaDataBtn;
|
return manageMetaDataBtn;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -244,7 +244,7 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable<SoftwareModul
|
|||||||
return name + "." + version;
|
return name + "." + version;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMetadataDetails(final Long itemId, final String nameVersionStr) {
|
private void showMetadataDetails(final Long itemId) {
|
||||||
final SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(itemId);
|
final SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(itemId);
|
||||||
/* display the window */
|
/* display the window */
|
||||||
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, null));
|
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, null));
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent;
|
|||||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
|
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum;
|
||||||
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
|
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
|
||||||
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
|
import org.eclipse.hawkbit.ui.common.SoftwareModuleTypeBeanQuery;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
import org.eclipse.hawkbit.ui.layouts.CreateUpdateTypeLayout;
|
import org.eclipse.hawkbit.ui.layouts.CreateUpdateTypeLayout;
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
@@ -35,6 +37,7 @@ import com.vaadin.spring.annotation.ViewScope;
|
|||||||
import com.vaadin.ui.Button.ClickEvent;
|
import com.vaadin.ui.Button.ClickEvent;
|
||||||
import com.vaadin.ui.Label;
|
import com.vaadin.ui.Label;
|
||||||
import com.vaadin.ui.OptionGroup;
|
import com.vaadin.ui.OptionGroup;
|
||||||
|
import com.vaadin.ui.TextField;
|
||||||
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
|
import com.vaadin.ui.components.colorpicker.ColorChangeListener;
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
@@ -74,29 +77,28 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout {
|
|||||||
|
|
||||||
singleAssignStr = i18n.get("label.singleAssign.type");
|
singleAssignStr = i18n.get("label.singleAssign.type");
|
||||||
multiAssignStr = i18n.get("label.multiAssign.type");
|
multiAssignStr = i18n.get("label.multiAssign.type");
|
||||||
singleAssign = SPUIComponentProvider.getLabel(singleAssignStr, null);
|
singleAssign = new LabelBuilder().name(singleAssignStr).buildLabel();
|
||||||
multiAssign = SPUIComponentProvider.getLabel(multiAssignStr, null);
|
|
||||||
|
|
||||||
tagName = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "",
|
multiAssign = new LabelBuilder().name(multiAssignStr).buildLabel();
|
||||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_NAME, true, "", i18n.get("textfield.name"), true,
|
|
||||||
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
tagName.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_NAME);
|
|
||||||
|
|
||||||
typeKey = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
|
tagName = createTextField("textfield.name", SPUIDefinitions.TYPE_NAME, SPUIDefinitions.NEW_SOFTWARE_TYPE_NAME);
|
||||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_KEY, true, "", i18n.get("textfield.key"), true,
|
|
||||||
SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
typeKey.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_KEY);
|
|
||||||
|
|
||||||
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
|
typeKey = createTextField("textfield.key", SPUIDefinitions.TYPE_KEY, SPUIDefinitions.NEW_SOFTWARE_TYPE_KEY);
|
||||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC, false, "",
|
|
||||||
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
|
tagDesc = new TextAreaBuilder().caption(i18n.get("textfield.description"))
|
||||||
tagDesc.setId(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC);
|
.styleName(ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.TYPE_DESC)
|
||||||
tagDesc.setImmediate(true);
|
.prompt(i18n.get("textfield.description")).immediate(true).id(SPUIDefinitions.NEW_SOFTWARE_TYPE_DESC)
|
||||||
|
.buildTextComponent();
|
||||||
tagDesc.setNullRepresentation("");
|
tagDesc.setNullRepresentation("");
|
||||||
|
|
||||||
singleMultiOptionGroup();
|
singleMultiOptionGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TextField createTextField(final String in18Key, final String styleName, final String id) {
|
||||||
|
return new TextFieldBuilder().caption(i18n.get(in18Key)).styleName(ValoTheme.TEXTFIELD_TINY + " " + styleName)
|
||||||
|
.required(true).prompt(i18n.get(in18Key)).immediate(true).id(id).buildTextComponent();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void buildLayout() {
|
protected void buildLayout() {
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.artifacts.upload;
|
package org.eclipse.hawkbit.ui.artifacts.upload;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions.FAILED;
|
||||||
|
import static org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions.SUCCESS;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -23,6 +26,7 @@ import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
|||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
|
import org.eclipse.hawkbit.ui.artifacts.state.CustomFile;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
|
||||||
@@ -56,13 +60,13 @@ import com.vaadin.ui.themes.ValoTheme;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Artifact upload confirmation popup.
|
* Artifact upload confirmation popup.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class UploadConfirmationwindow implements Button.ClickListener {
|
public class UploadConfirmationWindow implements Button.ClickListener {
|
||||||
|
|
||||||
private static final long serialVersionUID = -1679035890140031740L;
|
private static final long serialVersionUID = -1679035890140031740L;
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(UploadConfirmationwindow.class);
|
private static final Logger LOG = LoggerFactory.getLogger(UploadConfirmationWindow.class);
|
||||||
|
|
||||||
private static final String MD5_CHECKSUM = "md5Checksum";
|
private static final String MD5_CHECKSUM = "md5Checksum";
|
||||||
|
|
||||||
@@ -114,13 +118,13 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the upload confirmation window.
|
* Initialize the upload confirmation window.
|
||||||
*
|
*
|
||||||
* @param artifactUploadView
|
* @param artifactUploadView
|
||||||
* reference of upload layout.
|
* reference of upload layout.
|
||||||
* @param artifactUploadState
|
* @param artifactUploadState
|
||||||
* reference of session variable {@link ArtifactUploadState}.
|
* reference of session variable {@link ArtifactUploadState}.
|
||||||
*/
|
*/
|
||||||
public UploadConfirmationwindow(final UploadLayout artifactUploadView,
|
public UploadConfirmationWindow(final UploadLayout artifactUploadView,
|
||||||
final ArtifactUploadState artifactUploadState) {
|
final ArtifactUploadState artifactUploadState) {
|
||||||
this.uploadLayout = artifactUploadView;
|
this.uploadLayout = artifactUploadView;
|
||||||
this.artifactUploadState = artifactUploadState;
|
this.artifactUploadState = artifactUploadState;
|
||||||
@@ -245,29 +249,27 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
|||||||
deleteIcon.setData(itemId);
|
deleteIcon.setData(itemId);
|
||||||
newItem.getItemProperty(ACTION).setValue(deleteIcon);
|
newItem.getItemProperty(ACTION).setValue(deleteIcon);
|
||||||
|
|
||||||
final TextField sha1 = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null,
|
final TextField sha1 = createTextField(swNameVersion + "/" + customFile.getFileName() + "/sha1");
|
||||||
null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
sha1.setId(swNameVersion + "/" + customFile.getFileName() + "/sha1");
|
|
||||||
|
|
||||||
final TextField md5 = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY, false, null,
|
final TextField md5 = createTextField(swNameVersion + "/" + customFile.getFileName() + "/md5");
|
||||||
null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
md5.setId(swNameVersion + "/" + customFile.getFileName() + "/md5");
|
createTextField(swNameVersion + "/" + customFile.getFileName() + "/customFileName");
|
||||||
|
|
||||||
final TextField customFileName = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY,
|
|
||||||
false, null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
customFileName.setId(swNameVersion + "/" + customFile.getFileName() + "/customFileName");
|
|
||||||
newItem.getItemProperty(SHA1_CHECKSUM).setValue(sha1);
|
newItem.getItemProperty(SHA1_CHECKSUM).setValue(sha1);
|
||||||
newItem.getItemProperty(MD5_CHECKSUM).setValue(md5);
|
newItem.getItemProperty(MD5_CHECKSUM).setValue(md5);
|
||||||
newItem.getItemProperty(CUSTOM_FILE).setValue(customFile);
|
newItem.getItemProperty(CUSTOM_FILE).setValue(customFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static TextField createTextField(final String id) {
|
||||||
|
return new TextFieldBuilder().immediate(true).id(id).buildTextComponent();
|
||||||
|
}
|
||||||
|
|
||||||
private void addFileNameLayout(final Item newItem, final String baseSoftwareModuleNameVersion,
|
private void addFileNameLayout(final Item newItem, final String baseSoftwareModuleNameVersion,
|
||||||
final String customFileName, final String itemId) {
|
final String customFileName, final String itemId) {
|
||||||
final HorizontalLayout horizontalLayout = new HorizontalLayout();
|
final HorizontalLayout horizontalLayout = new HorizontalLayout();
|
||||||
final TextField fileNameTextField = SPUIComponentProvider.getTextField(null, "", ValoTheme.TEXTFIELD_TINY,
|
final TextField fileNameTextField = createTextField(
|
||||||
false, null, null, true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
baseSoftwareModuleNameVersion + "/" + customFileName + "/customFileName");
|
||||||
fileNameTextField.setId(baseSoftwareModuleNameVersion + "/" + customFileName + "/customFileName");
|
|
||||||
fileNameTextField.setData(baseSoftwareModuleNameVersion + "/" + customFileName);
|
fileNameTextField.setData(baseSoftwareModuleNameVersion + "/" + customFileName);
|
||||||
fileNameTextField.setValue(customFileName);
|
fileNameTextField.setValue(customFileName);
|
||||||
|
|
||||||
@@ -615,6 +617,7 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
|||||||
|
|
||||||
private void createLocalArtifact(final String itemId, final String filePath,
|
private void createLocalArtifact(final String itemId, final String filePath,
|
||||||
final ArtifactManagement artifactManagement, final SoftwareModule baseSw) {
|
final ArtifactManagement artifactManagement, final SoftwareModule baseSw) {
|
||||||
|
|
||||||
final File newFile = new File(filePath);
|
final File newFile = new File(filePath);
|
||||||
final Item item = tabelContainer.getItem(itemId);
|
final Item item = tabelContainer.getItem(itemId);
|
||||||
final String sha1Checksum = ((TextField) item.getItemProperty(SHA1_CHECKSUM).getValue()).getValue();
|
final String sha1Checksum = ((TextField) item.getItemProperty(SHA1_CHECKSUM).getValue()).getValue();
|
||||||
@@ -624,27 +627,25 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
|||||||
final String[] itemDet = itemId.split("/");
|
final String[] itemDet = itemId.split("/");
|
||||||
final String swModuleNameVersion = itemDet[0];
|
final String swModuleNameVersion = itemDet[0];
|
||||||
|
|
||||||
FileInputStream fis = null;
|
try (FileInputStream fis = new FileInputStream(newFile)) {
|
||||||
try {
|
|
||||||
fis = new FileInputStream(newFile);
|
|
||||||
artifactManagement.createLocalArtifact(fis, baseSw.getId(), providedFileName,
|
artifactManagement.createLocalArtifact(fis, baseSw.getId(), providedFileName,
|
||||||
HawkbitCommonUtil.trimAndNullIfEmpty(md5Checksum),
|
HawkbitCommonUtil.trimAndNullIfEmpty(md5Checksum),
|
||||||
HawkbitCommonUtil.trimAndNullIfEmpty(sha1Checksum), true, customFile.getMimeType());
|
HawkbitCommonUtil.trimAndNullIfEmpty(sha1Checksum), true, customFile.getMimeType());
|
||||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.SUCCESS, "");
|
saveUploadStatus(providedFileName, swModuleNameVersion, SUCCESS, "");
|
||||||
} catch (final FileNotFoundException e) {
|
|
||||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
} catch (final ArtifactUploadFailedException | InvalidSHA1HashException | InvalidMD5HashException
|
||||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
| FileNotFoundException e) {
|
||||||
} catch (final ArtifactUploadFailedException e) {
|
|
||||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
saveUploadStatus(providedFileName, swModuleNameVersion, FAILED, e.getMessage());
|
||||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
|
||||||
} catch (final InvalidSHA1HashException e) {
|
|
||||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
|
||||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
|
||||||
} catch (final InvalidMD5HashException e) {
|
|
||||||
saveUploadStatus(providedFileName, swModuleNameVersion, SPUILabelDefinitions.FAILED, e.getMessage());
|
|
||||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
||||||
|
|
||||||
|
} catch (final IOException ex) {
|
||||||
|
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, ex);
|
||||||
} finally {
|
} finally {
|
||||||
closeFileStream(fis, newFile);
|
if (newFile.exists() && !newFile.delete()) {
|
||||||
|
LOG.error("Could not delete temporary file: {}", newFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,21 +660,6 @@ public class UploadConfirmationwindow implements Button.ClickListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void closeFileStream(final FileInputStream fis, final File newFile) {
|
|
||||||
|
|
||||||
if (fis != null) {
|
|
||||||
try {
|
|
||||||
fis.close();
|
|
||||||
} catch (final IOException e) {
|
|
||||||
LOG.error(ARTIFACT_UPLOAD_EXCEPTION, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newFile.exists() && !newFile.delete()) {
|
|
||||||
LOG.error("Could not delete temporary file: {}", newFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Table getUploadDetailsTable() {
|
public Table getUploadDetailsTable() {
|
||||||
return uploadDetailsTable;
|
return uploadDetailsTable;
|
||||||
}
|
}
|
||||||
@@ -71,10 +71,10 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
private transient EventBus.SessionEventBus eventBus;
|
private transient EventBus.SessionEventBus eventBus;
|
||||||
private final SoftwareModule selectedSw;
|
private final SoftwareModule selectedSw;
|
||||||
private SoftwareModule selectedSwForUpload;
|
private SoftwareModule selectedSwForUpload;
|
||||||
private ArtifactUploadState artifactUploadState;
|
private final ArtifactUploadState artifactUploadState;
|
||||||
|
|
||||||
UploadHandler(final String fileName, final long fileSize, final UploadLayout view, final long maxSize,
|
UploadHandler(final String fileName, final long fileSize, final UploadLayout view, final long maxSize,
|
||||||
final Upload upload, final String mimeType, SoftwareModule selectedSw) {
|
final Upload upload, final String mimeType, final SoftwareModule selectedSw) {
|
||||||
super();
|
super();
|
||||||
this.aborted = false;
|
this.aborted = false;
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
@@ -142,7 +142,11 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
try {
|
try {
|
||||||
if (view.checkIfSoftwareModuleIsSelected() && !view.checkForDuplicate(fileName, selectedSwForUpload)) {
|
if (view.checkIfSoftwareModuleIsSelected() && !view.checkForDuplicate(fileName, selectedSwForUpload)) {
|
||||||
view.increaseNumberOfFileUploadsExpected();
|
view.increaseNumberOfFileUploadsExpected();
|
||||||
return view.saveUploadedFileDetails(fileName, 0, mimeType, selectedSwForUpload);
|
final OutputStream saveUploadedFileDetails = view.saveUploadedFileDetails(fileName, 0, mimeType,
|
||||||
|
selectedSwForUpload);
|
||||||
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.RECEIVE_UPLOAD,
|
||||||
|
new UploadFileStatus(fileName, 0, -1, selectedSwForUpload)));
|
||||||
|
return saveUploadedFileDetails;
|
||||||
}
|
}
|
||||||
} catch (final ArtifactUploadFailedException e) {
|
} catch (final ArtifactUploadFailedException e) {
|
||||||
LOG.error("Atifact upload failed {} ", e);
|
LOG.error("Atifact upload failed {} ", e);
|
||||||
@@ -163,8 +167,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
@Override
|
@Override
|
||||||
public void uploadSucceeded(final SucceededEvent event) {
|
public void uploadSucceeded(final SucceededEvent event) {
|
||||||
LOG.debug("Streaming finished for file :{}", event.getFilename());
|
LOG.debug("Streaming finished for file :{}", event.getFilename());
|
||||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_SUCCESSFUL, new UploadFileStatus(
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_SUCCESSFUL,
|
||||||
event.getFilename(), 0, event.getLength(), selectedSwForUpload)));
|
new UploadFileStatus(event.getFilename(), 0, event.getLength(), selectedSwForUpload)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -190,8 +194,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
@Override
|
@Override
|
||||||
public void uploadFinished(final FinishedEvent event) {
|
public void uploadFinished(final FinishedEvent event) {
|
||||||
LOG.debug("Upload finished for file :{}", event.getFilename());
|
LOG.debug("Upload finished for file :{}", event.getFilename());
|
||||||
eventBus.publish(this,
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FINISHED,
|
||||||
new UploadStatusEvent(UploadStatusEventType.UPLOAD_FINISHED, new UploadFileStatus(event.getFilename())));
|
new UploadFileStatus(event.getFilename())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -202,8 +206,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
@Override
|
@Override
|
||||||
public void streamingStarted(final StreamingStartEvent event) {
|
public void streamingStarted(final StreamingStartEvent event) {
|
||||||
LOG.debug("Streaming started for file :{}", fileName);
|
LOG.debug("Streaming started for file :{}", fileName);
|
||||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED, new UploadFileStatus(
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED,
|
||||||
fileName, 0, 0, selectedSw)));
|
new UploadFileStatus(fileName, 0, 0, selectedSw)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -214,8 +218,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
@Override
|
@Override
|
||||||
public void uploadStarted(final StartedEvent event) {
|
public void uploadStarted(final StartedEvent event) {
|
||||||
uploadInterrupted = false;
|
uploadInterrupted = false;
|
||||||
selectedSwForUpload = artifactUploadState.getSelectedBaseSoftwareModule().isPresent() ? artifactUploadState
|
selectedSwForUpload = artifactUploadState.getSelectedBaseSoftwareModule().isPresent()
|
||||||
.getSelectedBaseSoftwareModule().get() : null;
|
? artifactUploadState.getSelectedBaseSoftwareModule().get() : null;
|
||||||
|
|
||||||
if (view.isSoftwareModuleSelected()) {
|
if (view.isSoftwareModuleSelected()) {
|
||||||
// single file session
|
// single file session
|
||||||
@@ -223,9 +227,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
LOG.debug("Upload started for file :{}", event.getFilename());
|
LOG.debug("Upload started for file :{}", event.getFilename());
|
||||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED,
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_STARTED,
|
||||||
new UploadFileStatus(event.getFilename(), 0, 0, selectedSwForUpload)));
|
new UploadFileStatus(event.getFilename(), 0, 0, selectedSwForUpload)));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
failureReason = i18n.get("message.upload.failed");
|
failureReason = i18n.get("message.upload.failed");
|
||||||
upload.interruptUpload();
|
upload.interruptUpload();
|
||||||
// actual interrupt will happen a bit late so setting the below
|
// actual interrupt will happen a bit late so setting the below
|
||||||
@@ -291,8 +294,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
interruptFileStreaming();
|
interruptFileStreaming();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS, new UploadFileStatus(
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_IN_PROGRESS,
|
||||||
fileName, event.getBytesReceived(), event.getContentLength(), selectedSw)));
|
new UploadFileStatus(fileName, event.getBytesReceived(), event.getContentLength(), selectedSw)));
|
||||||
// Logging to solve sonar issue
|
// Logging to solve sonar issue
|
||||||
LOG.trace("Streaming in progress for file :{}", event.getFileName());
|
LOG.trace("Streaming in progress for file :{}", event.getFileName());
|
||||||
}
|
}
|
||||||
@@ -332,8 +335,8 @@ public class UploadHandler implements StreamVariable, Receiver, SucceededListene
|
|||||||
if (failureReason == null) {
|
if (failureReason == null) {
|
||||||
failureReason = event.getReason().getMessage();
|
failureReason = event.getReason().getMessage();
|
||||||
}
|
}
|
||||||
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED, new UploadFileStatus(
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.UPLOAD_FAILED,
|
||||||
fileName, failureReason, selectedSwForUpload)));
|
new UploadFileStatus(fileName, failureReason, selectedSwForUpload)));
|
||||||
if (!aborted) {
|
if (!aborted) {
|
||||||
LOG.info("Upload failed for file :{}", event.getFilename());
|
LOG.info("Upload failed for file :{}", event.getFilename());
|
||||||
LOG.info("Upload failed for file :{}", event.getReason());
|
LOG.info("Upload failed for file :{}", event.getReason());
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
|||||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
|
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
|
||||||
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadFileStatus;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
||||||
@@ -109,7 +110,7 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
|
|
||||||
private Button discardBtn;
|
private Button discardBtn;
|
||||||
|
|
||||||
private UploadConfirmationwindow currentUploadConfirmationwindow;
|
private UploadConfirmationWindow currentUploadConfirmationwindow;
|
||||||
|
|
||||||
private VerticalLayout dropAreaLayout;
|
private VerticalLayout dropAreaLayout;
|
||||||
|
|
||||||
@@ -273,6 +274,10 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
private void processFile(final Html5File file, final SoftwareModule selectedSw) {
|
private void processFile(final Html5File file, final SoftwareModule selectedSw) {
|
||||||
if (!isDirectory(file)) {
|
if (!isDirectory(file)) {
|
||||||
if (!checkForDuplicate(file.getFileName(), selectedSw)) {
|
if (!checkForDuplicate(file.getFileName(), selectedSw)) {
|
||||||
|
|
||||||
|
eventBus.publish(this, new UploadStatusEvent(UploadStatusEventType.RECEIVE_UPLOAD,
|
||||||
|
new UploadFileStatus(file.getFileName(), 0, -1, selectedSw)));
|
||||||
|
|
||||||
artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet();
|
artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet();
|
||||||
file.setStreamVariable(createStreamVariable(file, selectedSw));
|
file.setStreamVariable(createStreamVariable(file, selectedSw));
|
||||||
}
|
}
|
||||||
@@ -634,7 +639,7 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
if (artifactUploadState.getFileSelected().isEmpty()) {
|
if (artifactUploadState.getFileSelected().isEmpty()) {
|
||||||
uiNotification.displayValidationError(i18n.get("message.error.noFileSelected"));
|
uiNotification.displayValidationError(i18n.get("message.error.noFileSelected"));
|
||||||
} else {
|
} else {
|
||||||
currentUploadConfirmationwindow = new UploadConfirmationwindow(this, artifactUploadState);
|
currentUploadConfirmationwindow = new UploadConfirmationWindow(this, artifactUploadState);
|
||||||
UI.getCurrent().addWindow(currentUploadConfirmationwindow.getUploadConfrimationWindow());
|
UI.getCurrent().addWindow(currentUploadConfirmationwindow.getUploadConfrimationWindow());
|
||||||
setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(),
|
setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(),
|
||||||
Page.getCurrent().getBrowserWindowHeight());
|
Page.getCurrent().getBrowserWindowHeight());
|
||||||
@@ -656,7 +661,7 @@ public class UploadLayout extends VerticalLayout {
|
|||||||
return spInfo;
|
return spInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCurrentUploadConfirmationwindow(final UploadConfirmationwindow currentUploadConfirmationwindow) {
|
void setCurrentUploadConfirmationwindow(final UploadConfirmationWindow currentUploadConfirmationwindow) {
|
||||||
this.currentUploadConfirmationwindow = currentUploadConfirmationwindow;
|
this.currentUploadConfirmationwindow = currentUploadConfirmationwindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import javax.annotation.PreDestroy;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent;
|
||||||
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadFileStatus;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
|
import org.eclipse.hawkbit.ui.artifacts.event.UploadStatusEvent.UploadStatusEventType;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState;
|
||||||
@@ -56,11 +57,7 @@ import elemental.json.JsonValue;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows upload status during upload.
|
* Shows upload status during upload.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ViewScope
|
@ViewScope
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
public class UploadStatusInfoWindow extends Window {
|
public class UploadStatusInfoWindow extends Window {
|
||||||
@@ -135,26 +132,36 @@ public class UploadStatusInfoWindow extends Window {
|
|||||||
|
|
||||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||||
void onEvent(final UploadStatusEvent event) {
|
void onEvent(final UploadStatusEvent event) {
|
||||||
if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_IN_PROGRESS) {
|
|
||||||
UI.getCurrent().access(
|
final UploadFileStatus uploadStatus = event.getUploadStatus();
|
||||||
() -> updateProgress(event.getUploadStatus().getFileName(), event.getUploadStatus().getBytesRead(),
|
switch (event.getUploadProgressEventType()) {
|
||||||
event.getUploadStatus().getContentLength(), event.getUploadStatus().getSoftwareModule()));
|
case UPLOAD_IN_PROGRESS:
|
||||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STARTED) {
|
ui.access(() -> updateProgress(uploadStatus.getFileName(), uploadStatus.getBytesRead(),
|
||||||
UI.getCurrent().access(() -> onStartOfUpload(event));
|
uploadStatus.getContentLength(), uploadStatus.getSoftwareModule()));
|
||||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FAILED) {
|
break;
|
||||||
ui.access(() -> uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus()
|
case UPLOAD_STARTED:
|
||||||
.getFailureReason(), event.getUploadStatus().getSoftwareModule()));
|
ui.access(() -> onStartOfUpload(event));
|
||||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_SUCCESSFUL) {
|
break;
|
||||||
UI.getCurrent().access(
|
case UPLOAD_STREAMING_FAILED:
|
||||||
() -> uploadSucceeded(event.getUploadStatus().getFileName(), event.getUploadStatus()
|
ui.access(() -> uploadFailed(uploadStatus.getFileName(), uploadStatus.getFailureReason(),
|
||||||
.getSoftwareModule()));
|
uploadStatus.getSoftwareModule()));
|
||||||
} else if (event.getUploadProgressEventType() == UploadStatusEventType.UPLOAD_STREAMING_FINISHED) {
|
break;
|
||||||
ui.access(() -> uploadSucceeded(event.getUploadStatus().getFileName(), event.getUploadStatus()
|
case UPLOAD_SUCCESSFUL:
|
||||||
.getSoftwareModule()));
|
// fall through here
|
||||||
|
case UPLOAD_STREAMING_FINISHED:
|
||||||
|
ui.access(() -> uploadSucceeded(uploadStatus.getFileName(), uploadStatus.getSoftwareModule()));
|
||||||
|
break;
|
||||||
|
case RECEIVE_UPLOAD:
|
||||||
|
uploadRecevied(uploadStatus.getFileName(), uploadStatus.getSoftwareModule());
|
||||||
|
break;
|
||||||
|
case UPLOAD_FINISHED:
|
||||||
|
case ABORT_UPLOAD:
|
||||||
|
case UPLOAD_FAILED:
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onStartOfUpload(UploadStatusEvent event) {
|
private void onStartOfUpload(final UploadStatusEvent event) {
|
||||||
uploadSessionStarted();
|
uploadSessionStarted();
|
||||||
uploadStarted(event.getUploadStatus().getFileName(), event.getUploadStatus().getSoftwareModule());
|
uploadStarted(event.getUploadStatus().getFileName(), event.getUploadStatus().getSoftwareModule());
|
||||||
}
|
}
|
||||||
@@ -169,19 +176,23 @@ public class UploadStatusInfoWindow extends Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void restoreState() {
|
private void restoreState() {
|
||||||
Indexed container = grid.getContainerDataSource();
|
final Indexed container = grid.getContainerDataSource();
|
||||||
if (container.getItemIds().isEmpty()) {
|
if (container.getItemIds().isEmpty()) {
|
||||||
container.removeAllItems();
|
container.removeAllItems();
|
||||||
for (UploadStatusObject statusObject : artifactUploadState.getUploadedFileStatusList()) {
|
for (final UploadStatusObject statusObject : artifactUploadState.getUploadedFileStatusList()) {
|
||||||
Item item = container.addItem(getItemid(statusObject.getFilename(),
|
final Item item = container
|
||||||
statusObject.getSelectedSoftwareModule()));
|
.addItem(getItemid(statusObject.getFilename(), statusObject.getSelectedSoftwareModule()));
|
||||||
item.getItemProperty(REASON).setValue(statusObject.getReason() != null ? statusObject.getReason() : "");
|
item.getItemProperty(REASON).setValue(statusObject.getReason() != null ? statusObject.getReason() : "");
|
||||||
item.getItemProperty(STATUS).setValue(statusObject.getStatus());
|
if (statusObject.getStatus() != null) {
|
||||||
item.getItemProperty(PROGRESS).setValue(statusObject.getProgress());
|
item.getItemProperty(STATUS).setValue(statusObject.getStatus());
|
||||||
|
}
|
||||||
|
if (statusObject.getProgress() != null) {
|
||||||
|
item.getItemProperty(PROGRESS).setValue(statusObject.getProgress());
|
||||||
|
}
|
||||||
item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename());
|
item.getItemProperty(FILE_NAME).setValue(statusObject.getFilename());
|
||||||
SoftwareModule sw = statusObject.getSelectedSoftwareModule();
|
final SoftwareModule sw = statusObject.getSelectedSoftwareModule();
|
||||||
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION).setValue(
|
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION)
|
||||||
HawkbitCommonUtil.getFormattedNameVersion(sw.getName(), sw.getVersion()));
|
.setValue(HawkbitCommonUtil.getFormattedNameVersion(sw.getName(), sw.getVersion()));
|
||||||
}
|
}
|
||||||
if (artifactUploadState.isUploadCompleted()) {
|
if (artifactUploadState.isUploadCompleted()) {
|
||||||
minimizeButton.setEnabled(false);
|
minimizeButton.setEnabled(false);
|
||||||
@@ -209,7 +220,7 @@ public class UploadStatusInfoWindow extends Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Grid createGrid() {
|
private Grid createGrid() {
|
||||||
Grid statusGrid = new Grid(uploads);
|
final Grid statusGrid = new Grid(uploads);
|
||||||
statusGrid.addStyleName(SPUIStyleDefinitions.UPLOAD_STATUS_GRID);
|
statusGrid.addStyleName(SPUIStyleDefinitions.UPLOAD_STATUS_GRID);
|
||||||
statusGrid.setSelectionMode(SelectionMode.NONE);
|
statusGrid.setSelectionMode(SelectionMode.NONE);
|
||||||
statusGrid.setHeaderVisible(true);
|
statusGrid.setHeaderVisible(true);
|
||||||
@@ -219,7 +230,7 @@ public class UploadStatusInfoWindow extends Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IndexedContainer getGridContainer() {
|
private IndexedContainer getGridContainer() {
|
||||||
IndexedContainer uploadContainer = new IndexedContainer();
|
final IndexedContainer uploadContainer = new IndexedContainer();
|
||||||
uploadContainer.addContainerProperty(STATUS, String.class, "Active");
|
uploadContainer.addContainerProperty(STATUS, String.class, "Active");
|
||||||
uploadContainer.addContainerProperty(FILE_NAME, String.class, null);
|
uploadContainer.addContainerProperty(FILE_NAME, String.class, null);
|
||||||
uploadContainer.addContainerProperty(PROGRESS, Double.class, 0D);
|
uploadContainer.addContainerProperty(PROGRESS, Double.class, 0D);
|
||||||
@@ -321,72 +332,72 @@ public class UploadStatusInfoWindow extends Window {
|
|||||||
restoreState();
|
restoreState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void uploadStarted(final String filename, final SoftwareModule softwareModule) {
|
private void uploadRecevied(final String filename, final SoftwareModule softwareModule) {
|
||||||
final Item item = uploads.addItem(getItemid(filename, softwareModule));
|
final Item item = uploads.addItem(getItemid(filename, softwareModule));
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.getItemProperty(FILE_NAME).setValue(filename);
|
item.getItemProperty(FILE_NAME).setValue(filename);
|
||||||
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION).setValue(
|
item.getItemProperty(SPUILabelDefinitions.NAME_VERSION).setValue(
|
||||||
HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion()));
|
HawkbitCommonUtil.getFormattedNameVersion(softwareModule.getName(), softwareModule.getVersion()));
|
||||||
|
final UploadStatusObject uploadStatus = new UploadStatusObject(filename, softwareModule);
|
||||||
|
uploadStatus.setStatus("Active");
|
||||||
|
artifactUploadState.getUploadedFileStatusList().add(uploadStatus);
|
||||||
}
|
}
|
||||||
grid.scrollToEnd();
|
}
|
||||||
UploadStatusObject uploadStatus = new UploadStatusObject(filename, softwareModule);
|
|
||||||
uploadStatus.setStatus("Active");
|
void uploadStarted(final String filename, final SoftwareModule softwareModule) {
|
||||||
artifactUploadState.getUploadedFileStatusList().add(uploadStatus);
|
grid.scrollTo(getItemid(filename, softwareModule));
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateProgress(final String filename, final long readBytes, final long contentLength,
|
void updateProgress(final String filename, final long readBytes, final long contentLength,
|
||||||
final SoftwareModule softwareModule) {
|
final SoftwareModule softwareModule) {
|
||||||
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
||||||
double progress = (double) readBytes / (double) contentLength;
|
final double progress = (double) readBytes / (double) contentLength;
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.getItemProperty(PROGRESS).setValue(progress);
|
item.getItemProperty(PROGRESS).setValue(progress);
|
||||||
}
|
}
|
||||||
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
|
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
|
||||||
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
|
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!uploadStatusObjectList.isEmpty()) {
|
if (!uploadStatusObjectList.isEmpty()) {
|
||||||
UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||||
uploadStatusObject.setProgress(progress);
|
uploadStatusObject.setProgress(progress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when each file upload is success.
|
* Called when each file upload is success.
|
||||||
*
|
*
|
||||||
* @param filename
|
* @param filename
|
||||||
* of the uploaded file.
|
* of the uploaded file.
|
||||||
* @param softwareModule
|
* @param softwareModule
|
||||||
* selected software module
|
* selected software module
|
||||||
*/
|
*/
|
||||||
public void uploadSucceeded(final String filename, SoftwareModule softwareModule) {
|
public void uploadSucceeded(final String filename, final SoftwareModule softwareModule) {
|
||||||
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
||||||
String status = "Finished";
|
final String status = "Finished";
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.getItemProperty(STATUS).setValue(status);
|
item.getItemProperty(STATUS).setValue(status);
|
||||||
}
|
}
|
||||||
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
|
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
|
||||||
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
|
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!uploadStatusObjectList.isEmpty()) {
|
if (!uploadStatusObjectList.isEmpty()) {
|
||||||
UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||||
uploadStatusObject.setStatus(status);
|
uploadStatusObject.setStatus(status);
|
||||||
uploadStatusObject.setProgress(1d);
|
uploadStatusObject.setProgress(1d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void uploadFailed(final String filename, final String errorReason, SoftwareModule softwareModule) {
|
void uploadFailed(final String filename, final String errorReason, final SoftwareModule softwareModule) {
|
||||||
errorOccured = true;
|
errorOccured = true;
|
||||||
String status = "Failed";
|
final String status = "Failed";
|
||||||
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
final Item item = uploads.getItem(getItemid(filename, softwareModule));
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.getItemProperty(REASON).setValue(errorReason);
|
item.getItemProperty(REASON).setValue(errorReason);
|
||||||
item.getItemProperty(STATUS).setValue(status);
|
item.getItemProperty(STATUS).setValue(status);
|
||||||
}
|
}
|
||||||
List<UploadStatusObject> uploadStatusObjectList = (List<UploadStatusObject>) artifactUploadState
|
final List<UploadStatusObject> uploadStatusObjectList = artifactUploadState.getUploadedFileStatusList().stream()
|
||||||
.getUploadedFileStatusList().stream().filter(e -> e.getFilename().equals(filename))
|
.filter(e -> e.getFilename().equals(filename)).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
|
||||||
if (!uploadStatusObjectList.isEmpty()) {
|
if (!uploadStatusObjectList.isEmpty()) {
|
||||||
UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
final UploadStatusObject uploadStatusObject = uploadStatusObjectList.get(0);
|
||||||
uploadStatusObject.setStatus(status);
|
uploadStatusObject.setStatus(status);
|
||||||
uploadStatusObject.setReason(errorReason);
|
uploadStatusObject.setReason(errorReason);
|
||||||
}
|
}
|
||||||
@@ -428,8 +439,8 @@ public class UploadStatusInfoWindow extends Window {
|
|||||||
return resizeBtn;
|
return resizeBtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resizeWindow(ClickEvent event) {
|
private void resizeWindow(final ClickEvent event) {
|
||||||
if (event.getButton().getIcon() == FontAwesome.EXPAND) {
|
if (FontAwesome.EXPAND.equals(event.getButton().getIcon())) {
|
||||||
event.getButton().setIcon(FontAwesome.COMPRESS);
|
event.getButton().setIcon(FontAwesome.COMPRESS);
|
||||||
setWindowMode(WindowMode.MAXIMIZED);
|
setWindowMode(WindowMode.MAXIMIZED);
|
||||||
resetColumnWidth();
|
resetColumnWidth();
|
||||||
|
|||||||
@@ -16,15 +16,17 @@ import javax.annotation.PostConstruct;
|
|||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||||
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
|
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
|
import org.eclipse.hawkbit.ui.customrenderers.renderers.HtmlButtonRenderer;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -48,7 +50,6 @@ import com.vaadin.ui.TextField;
|
|||||||
import com.vaadin.ui.UI;
|
import com.vaadin.ui.UI;
|
||||||
import com.vaadin.ui.VerticalLayout;
|
import com.vaadin.ui.VerticalLayout;
|
||||||
import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent;
|
import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent;
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -115,9 +116,11 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
|||||||
public CommonDialogWindow getWindow(final E entity, final M metaData) {
|
public CommonDialogWindow getWindow(final E entity, final M metaData) {
|
||||||
selectedEntity = entity;
|
selectedEntity = entity;
|
||||||
final String nameVersion = HawkbitCommonUtil.getFormattedNameVersion(entity.getName(), entity.getVersion());
|
final String nameVersion = HawkbitCommonUtil.getFormattedNameVersion(entity.getName(), entity.getVersion());
|
||||||
metadataWindow = SPUIWindowDecorator.getWindow(getMetadataCaption(nameVersion), null,
|
|
||||||
SPUIDefinitions.CUSTOM_METADATA_WINDOW, this, event -> onSave(), event -> onCancel(), null, mainLayout,
|
metadataWindow = new WindowBuilder(SPUIDefinitions.CUSTOM_METADATA_WINDOW)
|
||||||
i18n);
|
.caption(getMetadataCaption(nameVersion)).content(this).saveButtonClickListener(event -> onSave())
|
||||||
|
.cancelButtonClickListener(event -> onCancel()).layout(mainLayout).i18n(i18n).buildCommonDialogWindow();
|
||||||
|
|
||||||
metadataWindow.setId(SPUIComponentIdProvider.METADATA_POPUP_ID);
|
metadataWindow.setId(SPUIComponentIdProvider.METADATA_POPUP_ID);
|
||||||
metadataWindow.setHeight(550, Unit.PIXELS);
|
metadataWindow.setHeight(550, Unit.PIXELS);
|
||||||
metadataWindow.setWidth(800, Unit.PIXELS);
|
metadataWindow.setWidth(800, Unit.PIXELS);
|
||||||
@@ -204,9 +207,9 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TextField createKeyTextField() {
|
private TextField createKeyTextField() {
|
||||||
final TextField keyField = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
|
final TextField keyField = new TextFieldBuilder().caption(i18n.get("textfield.key")).required(true)
|
||||||
ValoTheme.TEXTFIELD_TINY, true, "", i18n.get("textfield.key"), true, 128);
|
.prompt(i18n.get("textfield.key")).immediate(true).id(SPUIComponentIdProvider.METADATA_KEY_FIELD_ID)
|
||||||
keyField.setId(SPUIComponentIdProvider.METADATA_KEY_FIELD_ID);
|
.maxLengthAllowed(128).buildTextComponent();
|
||||||
keyField.addTextChangeListener(event -> onKeyChange(event));
|
keyField.addTextChangeListener(event -> onKeyChange(event));
|
||||||
keyField.setTextChangeEventMode(TextChangeEventMode.EAGER);
|
keyField.setTextChangeEventMode(TextChangeEventMode.EAGER);
|
||||||
keyField.setWidth("100%");
|
keyField.setWidth("100%");
|
||||||
@@ -214,9 +217,9 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TextArea createValueTextField() {
|
private TextArea createValueTextField() {
|
||||||
valueTextArea = SPUIComponentProvider.getTextArea(i18n.get("textfield.value"), null, ValoTheme.TEXTAREA_TINY,
|
valueTextArea = new TextAreaBuilder().caption(i18n.get("textfield.value")).required(true)
|
||||||
true, null, i18n.get("textfield.value"), 4000);
|
.prompt(i18n.get("textfield.value")).immediate(true).id(SPUIComponentIdProvider.METADATA_VALUE_ID)
|
||||||
valueTextArea.setId(SPUIComponentIdProvider.METADATA_VALUE_ID);
|
.maxLengthAllowed(4000).buildTextComponent();
|
||||||
valueTextArea.setNullRepresentation("");
|
valueTextArea.setNullRepresentation("");
|
||||||
valueTextArea.setSizeFull();
|
valueTextArea.setSizeFull();
|
||||||
valueTextArea.setHeight(100, Unit.PERCENTAGE);
|
valueTextArea.setHeight(100, Unit.PERCENTAGE);
|
||||||
@@ -301,7 +304,7 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Label createHeaderCaption() {
|
private Label createHeaderCaption() {
|
||||||
return SPUIComponentProvider.getLabel(i18n.get("caption.metadata"), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
return new LabelBuilder().name(i18n.get("caption.metadata")).buildCaptionLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IndexedContainer getMetadataContainer() {
|
private static IndexedContainer getMetadataContainer() {
|
||||||
@@ -407,9 +410,9 @@ public abstract class AbstractMetadataPopupLayout<E extends NamedVersionedEntity
|
|||||||
|
|
||||||
private String getMetadataCaption(final String nameVersionStr) {
|
private String getMetadataCaption(final String nameVersionStr) {
|
||||||
final StringBuilder caption = new StringBuilder();
|
final StringBuilder caption = new StringBuilder();
|
||||||
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION + i18n.get("caption.metadata.popup") + " "
|
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION_START + i18n.get("caption.metadata.popup") + " "
|
||||||
+ HawkbitCommonUtil.getBoldHTMLText(nameVersionStr));
|
+ HawkbitCommonUtil.getBoldHTMLText(nameVersionStr));
|
||||||
caption.append(HawkbitCommonUtil.DIV_CLOSE);
|
caption.append(HawkbitCommonUtil.DIV_DESCRIPTION_END);
|
||||||
return caption.toString();
|
return caption.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ package org.eclipse.hawkbit.ui.common;
|
|||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -70,7 +69,7 @@ import com.vaadin.ui.themes.ValoTheme;
|
|||||||
* corner and a save and cancel button at the bottom. Is not intended to reuse.
|
* corner and a save and cancel button at the bottom. Is not intended to reuse.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CommonDialogWindow extends Window implements Serializable {
|
public class CommonDialogWindow extends Window {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,6 @@ import com.vaadin.ui.AbstractColorPicker.Coordinates2Color;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts 2d-coordinates to a Color.
|
* Converts 2d-coordinates to a Color.
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class CoordinatesToColor implements Coordinates2Color {
|
public class CoordinatesToColor implements Coordinates2Color {
|
||||||
|
|
||||||
@@ -30,32 +26,31 @@ public class CoordinatesToColor implements Coordinates2Color {
|
|||||||
@Override
|
@Override
|
||||||
public int[] calculate(final Color color) {
|
public int[] calculate(final Color color) {
|
||||||
final float[] hsv = color.getHSV();
|
final float[] hsv = color.getHSV();
|
||||||
final int x = Math.round(hsv[0] * 220f);
|
final int x = Math.round(hsv[0] * 220F);
|
||||||
int y = 0;
|
final int y = calculateYCoordinateOfColor(hsv);
|
||||||
y = calculateYCoordinateOfColor(hsv);
|
|
||||||
return new int[] { x, y };
|
return new int[] { x, y };
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color calculateHSVColor(final int x, final int y) {
|
private static Color calculateHSVColor(final int x, final int y) {
|
||||||
final float h = x / 220f;
|
final float h = x / 220F;
|
||||||
float s = 1f;
|
float s = 1F;
|
||||||
float v = 1f;
|
float v = 1F;
|
||||||
if (y < 110) {
|
if (y < 110) {
|
||||||
s = y / 110f;
|
s = y / 110F;
|
||||||
} else if (y > 110) {
|
} else if (y > 110) {
|
||||||
v = 1f - (y - 110f) / 110f;
|
v = 1F - (y - 110F) / 110F;
|
||||||
}
|
}
|
||||||
return new Color(Color.HSVtoRGB(h, s, v));
|
return new Color(Color.HSVtoRGB(h, s, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateYCoordinateOfColor(final float[] hsv) {
|
private static int calculateYCoordinateOfColor(final float[] hsv) {
|
||||||
int y;
|
int y;
|
||||||
// lower half
|
// lower half
|
||||||
/* Assuming hsv[] array value will have in the range of 0 to 1 */
|
/* Assuming hsv[] array value will have in the range of 0 to 1 */
|
||||||
if (hsv[1] < 1f) {
|
if (hsv[1] < 1F) {
|
||||||
y = Math.round(hsv[1] * 110f);
|
y = Math.round(hsv[1] * 110F);
|
||||||
} else {
|
} else {
|
||||||
y = Math.round(110f - (hsv[1] + hsv[2]) * 110f);
|
y = Math.round(110F - (hsv[1] + hsv[2]) * 110F);
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
/**
|
||||||
|
* 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.builder;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import com.vaadin.ui.AbstractTextField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract Text field builder.
|
||||||
|
*
|
||||||
|
* @param <E>
|
||||||
|
* the concrete text component
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTextFieldBuilder<E extends AbstractTextField> {
|
||||||
|
|
||||||
|
private String caption;
|
||||||
|
private String style;
|
||||||
|
private String styleName;
|
||||||
|
private String prompt;
|
||||||
|
private String id;
|
||||||
|
private boolean immediate;
|
||||||
|
private boolean required;
|
||||||
|
private int maxLengthAllowed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param caption
|
||||||
|
* the caption to set
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> caption(final String caption) {
|
||||||
|
this.caption = caption;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param style
|
||||||
|
* the style to set * @return the builder
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> style(final String style) {
|
||||||
|
this.style = style;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param styleName
|
||||||
|
* the styleName to set
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> styleName(final String styleName) {
|
||||||
|
this.styleName = styleName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param required
|
||||||
|
* the required to set
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> required(final boolean required) {
|
||||||
|
this.required = required;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prompt
|
||||||
|
* the prompt to set
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> prompt(final String prompt) {
|
||||||
|
this.prompt = prompt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param immediate
|
||||||
|
* the immediate to set
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> immediate(final boolean immediate) {
|
||||||
|
this.immediate = immediate;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param maxLengthAllowed
|
||||||
|
* the maxLengthAllowed to set
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> maxLengthAllowed(final int maxLengthAllowed) {
|
||||||
|
this.maxLengthAllowed = maxLengthAllowed;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id
|
||||||
|
* the id to set
|
||||||
|
* @return the builder
|
||||||
|
*/
|
||||||
|
public AbstractTextFieldBuilder<E> id(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a textfield
|
||||||
|
*
|
||||||
|
* @return textfield
|
||||||
|
*/
|
||||||
|
public E buildTextComponent() {
|
||||||
|
final E textComponent = createTextComponent();
|
||||||
|
|
||||||
|
textComponent.setRequired(required);
|
||||||
|
textComponent.setImmediate(immediate);
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(caption)) {
|
||||||
|
textComponent.setCaption(caption);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(style)) {
|
||||||
|
textComponent.setStyleName(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(styleName)) {
|
||||||
|
textComponent.addStyleName(styleName);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotEmpty(prompt)) {
|
||||||
|
textComponent.setInputPrompt(prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxLengthAllowed > 0) {
|
||||||
|
textComponent.setMaxLength(maxLengthAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(id)) {
|
||||||
|
textComponent.setId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return textComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract E createTextComponent();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* 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.builder;
|
||||||
|
|
||||||
|
import com.vaadin.ui.Label;
|
||||||
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label Builder.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class LabelBuilder {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private boolean visible = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* the name to set
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public LabelBuilder name(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id
|
||||||
|
* the id to set
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public LabelBuilder id(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param visible
|
||||||
|
* the visible to set
|
||||||
|
* @return builder
|
||||||
|
*/
|
||||||
|
public LabelBuilder visible(final boolean visible) {
|
||||||
|
this.visible = visible;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build caption label.
|
||||||
|
*
|
||||||
|
* @return Label
|
||||||
|
*/
|
||||||
|
public Label buildCaptionLabel() {
|
||||||
|
final Label label = createLabel();
|
||||||
|
label.setValue(name);
|
||||||
|
label.addStyleName("header-caption");
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build label.
|
||||||
|
*
|
||||||
|
* @return Label
|
||||||
|
*/
|
||||||
|
public Label buildLabel() {
|
||||||
|
final Label label = createLabel();
|
||||||
|
label.setImmediate(false);
|
||||||
|
label.setWidth("-1px");
|
||||||
|
label.setHeight("-1px");
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Label createLabel() {
|
||||||
|
final Label label = new Label(name);
|
||||||
|
label.setVisible(visible);
|
||||||
|
final StringBuilder style = new StringBuilder(ValoTheme.LABEL_SMALL);
|
||||||
|
style.append(' ');
|
||||||
|
style.append(ValoTheme.LABEL_BOLD);
|
||||||
|
label.addStyleName(style.toString());
|
||||||
|
if (id != null) {
|
||||||
|
label.setId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.common.builder;
|
||||||
|
|
||||||
|
import com.vaadin.ui.TextArea;
|
||||||
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TextArea builder.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TextAreaBuilder extends AbstractTextFieldBuilder<TextArea> {
|
||||||
|
|
||||||
|
private static final int TEXT_AREA_DEFAULT_MAX_LENGTH = 512;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public TextAreaBuilder() {
|
||||||
|
maxLengthAllowed(TEXT_AREA_DEFAULT_MAX_LENGTH);
|
||||||
|
styleName(ValoTheme.TEXTAREA_TINY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TextArea createTextComponent() {
|
||||||
|
final TextArea textArea = new TextArea();
|
||||||
|
textArea.addStyleName(ValoTheme.TEXTAREA_SMALL);
|
||||||
|
return textArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* 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.builder;
|
||||||
|
|
||||||
|
import com.vaadin.event.FieldEvents.TextChangeListener;
|
||||||
|
import com.vaadin.server.Sizeable.Unit;
|
||||||
|
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
||||||
|
import com.vaadin.ui.TextField;
|
||||||
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Textfield builder.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TextFieldBuilder extends AbstractTextFieldBuilder<TextField> {
|
||||||
|
|
||||||
|
private static final int TEXT_FIELD_DEFAULT_MAX_LENGTH = 64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public TextFieldBuilder() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* the id
|
||||||
|
*/
|
||||||
|
public TextFieldBuilder(final String id) {
|
||||||
|
maxLengthAllowed(TEXT_FIELD_DEFAULT_MAX_LENGTH);
|
||||||
|
styleName(ValoTheme.TEXTAREA_TINY);
|
||||||
|
id(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a search text field.
|
||||||
|
*
|
||||||
|
* @param textChangeListener
|
||||||
|
* listener when text is changed.
|
||||||
|
* @return the textfield
|
||||||
|
*/
|
||||||
|
public TextField createSearchField(final TextChangeListener textChangeListener) {
|
||||||
|
final TextField textField = style("filter-box").styleName("text-style filter-box-hide").buildTextComponent();
|
||||||
|
textField.setWidth(100.0F, Unit.PERCENTAGE);
|
||||||
|
textField.addTextChangeListener(textChangeListener);
|
||||||
|
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
|
||||||
|
// 1 seconds timeout.
|
||||||
|
textField.setTextChangeTimeout(1000);
|
||||||
|
return textField;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TextField createTextComponent() {
|
||||||
|
final TextField textField = new TextField();
|
||||||
|
textField.addStyleName(ValoTheme.TEXTFIELD_SMALL);
|
||||||
|
return textField;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,200 @@
|
|||||||
|
/**
|
||||||
|
* 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.builder;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
|
||||||
|
import org.eclipse.hawkbit.ui.common.CustomCommonDialogWindow;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
|
|
||||||
|
import com.vaadin.ui.AbstractLayout;
|
||||||
|
import com.vaadin.ui.Button.ClickListener;
|
||||||
|
import com.vaadin.ui.Component;
|
||||||
|
import com.vaadin.ui.Window;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder for Window.
|
||||||
|
*/
|
||||||
|
public class WindowBuilder {
|
||||||
|
|
||||||
|
private String caption;
|
||||||
|
private Component content;
|
||||||
|
private ClickListener saveButtonClickListener;
|
||||||
|
private ClickListener cancelButtonClickListener;
|
||||||
|
private String helpLink;
|
||||||
|
private AbstractLayout layout;
|
||||||
|
private I18N i18n;
|
||||||
|
private final String type;
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* window type
|
||||||
|
*/
|
||||||
|
public WindowBuilder(final String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the caption.
|
||||||
|
*
|
||||||
|
* @param caption
|
||||||
|
* the caption
|
||||||
|
* @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder caption(final String caption) {
|
||||||
|
this.caption = caption;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the content.
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* the content
|
||||||
|
* @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder content(final Component content) {
|
||||||
|
this.content = content;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the saveButtonClickListener.
|
||||||
|
*
|
||||||
|
* @param saveButtonClickListener
|
||||||
|
* the saveButtonClickListener
|
||||||
|
* @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder saveButtonClickListener(final ClickListener saveButtonClickListener) {
|
||||||
|
this.saveButtonClickListener = saveButtonClickListener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the cancelButtonClickListener.
|
||||||
|
*
|
||||||
|
* @param cancelButtonClickListener
|
||||||
|
* the cancelButtonClickListener
|
||||||
|
* @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder cancelButtonClickListener(final ClickListener cancelButtonClickListener) {
|
||||||
|
this.cancelButtonClickListener = cancelButtonClickListener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the helpLink.
|
||||||
|
*
|
||||||
|
* @param helpLink
|
||||||
|
* the helpLink
|
||||||
|
* @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder helpLink(final String helpLink) {
|
||||||
|
this.helpLink = helpLink;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the layout.
|
||||||
|
*
|
||||||
|
* @param layout
|
||||||
|
* the layout
|
||||||
|
* @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder layout(final AbstractLayout layout) {
|
||||||
|
this.layout = layout;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the i18n.
|
||||||
|
*
|
||||||
|
* @param i18n
|
||||||
|
* the i18n
|
||||||
|
* @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder i18n(final I18N i18n) {
|
||||||
|
this.i18n = i18n;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id
|
||||||
|
* the id to set * @return the window builder
|
||||||
|
*/
|
||||||
|
public WindowBuilder id(final String id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the common dialog window.
|
||||||
|
*
|
||||||
|
* @return the window.
|
||||||
|
*/
|
||||||
|
public CommonDialogWindow buildCommonDialogWindow() {
|
||||||
|
CommonDialogWindow window;
|
||||||
|
|
||||||
|
if (SPUIDefinitions.CUSTOM_METADATA_WINDOW.equals(type)) {
|
||||||
|
window = new CustomCommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
|
||||||
|
cancelButtonClickListener, layout, i18n);
|
||||||
|
window.setDraggable(true);
|
||||||
|
window.setClosable(true);
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener, cancelButtonClickListener,
|
||||||
|
layout, i18n);
|
||||||
|
|
||||||
|
decorateWindow(window);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void decorateWindow(final Window window) {
|
||||||
|
if (id != null) {
|
||||||
|
window.setId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) {
|
||||||
|
window.setDraggable(false);
|
||||||
|
window.setClosable(true);
|
||||||
|
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
|
||||||
|
|
||||||
|
} else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
||||||
|
window.setDraggable(true);
|
||||||
|
window.setClosable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build window based on type.
|
||||||
|
*
|
||||||
|
* @return Window
|
||||||
|
*/
|
||||||
|
public Window buildWindow() {
|
||||||
|
final Window window = new Window(caption);
|
||||||
|
window.setContent(content);
|
||||||
|
window.setSizeUndefined();
|
||||||
|
window.setModal(true);
|
||||||
|
window.setResizable(false);
|
||||||
|
|
||||||
|
decorateWindow(window);
|
||||||
|
|
||||||
|
if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
||||||
|
window.setClosable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import java.util.Map.Entry;
|
|||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
@@ -51,6 +52,9 @@ public abstract class AbstractConfirmationWindowLayout extends VerticalLayout {
|
|||||||
@Autowired
|
@Autowired
|
||||||
protected transient EventBus.SessionEventBus eventBus;
|
protected transient EventBus.SessionEventBus eventBus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostConstruct.
|
||||||
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
removeAllComponents();
|
removeAllComponents();
|
||||||
@@ -65,10 +69,9 @@ public abstract class AbstractConfirmationWindowLayout extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createActionMessgaeLabel() {
|
private void createActionMessgaeLabel() {
|
||||||
actionMessage = SPUIComponentProvider.getLabel("", null);
|
actionMessage = new LabelBuilder().name("").id(SPUIComponentIdProvider.ACTION_LABEL).visible(false)
|
||||||
|
.buildLabel();
|
||||||
actionMessage.addStyleName(SPUIStyleDefinitions.CONFIRM_WINDOW_INFO_BOX);
|
actionMessage.addStyleName(SPUIStyleDefinitions.CONFIRM_WINDOW_INFO_BOX);
|
||||||
actionMessage.setId(SPUIComponentIdProvider.ACTION_LABEL);
|
|
||||||
actionMessage.setVisible(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createAccordian() {
|
private void createAccordian() {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent;
|
import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent;
|
||||||
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
@@ -25,7 +26,6 @@ import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
|||||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.vaadin.spring.events.EventBus;
|
import org.vaadin.spring.events.EventBus;
|
||||||
@@ -183,7 +183,7 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Label createHeaderCaption() {
|
private Label createHeaderCaption() {
|
||||||
return SPUIComponentProvider.getLabel(getDefaultCaption(), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
return new LabelBuilder().name(getDefaultCaption()).buildCaptionLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected VerticalLayout getTabLayout() {
|
protected VerticalLayout getTabLayout() {
|
||||||
@@ -222,7 +222,6 @@ public abstract class AbstractTableDetailsLayout<T extends NamedEntity> extends
|
|||||||
populateLog();
|
populateLog();
|
||||||
populateDescription();
|
populateDescription();
|
||||||
populateDetailsWidget();
|
populateDetailsWidget();
|
||||||
populateMetadataDetails();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateLog() {
|
protected void populateLog() {
|
||||||
|
|||||||
@@ -33,45 +33,44 @@ import com.vaadin.ui.UI;
|
|||||||
import com.vaadin.ui.themes.ValoTheme;
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* DistributionSet Metadata details layout.
|
* DistributionSet Metadata details layout.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@SpringComponent
|
@SpringComponent
|
||||||
@VaadinSessionScope
|
@VaadinSessionScope
|
||||||
public class DistributionSetMetadatadetailslayout extends Table{
|
public class DistributionSetMetadatadetailslayout extends Table {
|
||||||
|
|
||||||
private static final long serialVersionUID = 2913758299611837718L;
|
private static final long serialVersionUID = 2913758299611837718L;
|
||||||
|
|
||||||
|
|
||||||
private DistributionSetManagement distributionSetManagement;
|
|
||||||
|
|
||||||
private DsMetadataPopupLayout dsMetadataPopupLayout;
|
|
||||||
|
|
||||||
private static final String METADATA_KEY = "Key";
|
private static final String METADATA_KEY = "Key";
|
||||||
|
|
||||||
private static final String VIEW ="view";
|
private static final String VIEW = "view";
|
||||||
|
|
||||||
|
private transient DistributionSetManagement distributionSetManagement;
|
||||||
|
|
||||||
|
private DsMetadataPopupLayout dsMetadataPopupLayout;
|
||||||
|
|
||||||
private SpPermissionChecker permissionChecker;
|
private SpPermissionChecker permissionChecker;
|
||||||
|
|
||||||
private transient EntityFactory entityFactory;
|
private transient EntityFactory entityFactory;
|
||||||
|
|
||||||
private I18N i18n;
|
private I18N i18n;
|
||||||
|
|
||||||
private Long selectedDistSetId;
|
private Long selectedDistSetId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param i18n
|
* @param i18n
|
||||||
* @param permissionChecker
|
* @param permissionChecker
|
||||||
* @param distributionSetManagement
|
* @param distributionSetManagement
|
||||||
* @param dsMetadataPopupLayout
|
* @param dsMetadataPopupLayout
|
||||||
*/
|
* @param entityFactory
|
||||||
|
*/
|
||||||
public void init(final I18N i18n, final SpPermissionChecker permissionChecker,
|
public void init(final I18N i18n, final SpPermissionChecker permissionChecker,
|
||||||
final DistributionSetManagement distributionSetManagement,
|
final DistributionSetManagement distributionSetManagement,
|
||||||
final DsMetadataPopupLayout dsMetadataPopupLayout,
|
final DsMetadataPopupLayout dsMetadataPopupLayout, final EntityFactory entityFactory) {
|
||||||
final EntityFactory entityFactory) {
|
|
||||||
this.i18n = i18n;
|
this.i18n = i18n;
|
||||||
this.permissionChecker = permissionChecker;
|
this.permissionChecker = permissionChecker;
|
||||||
this.distributionSetManagement = distributionSetManagement;
|
this.distributionSetManagement = distributionSetManagement;
|
||||||
@@ -80,45 +79,24 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
|||||||
createDSMetadataTable();
|
createDSMetadataTable();
|
||||||
addCustomGeneratedColumns();
|
addCustomGeneratedColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate software module metadata.
|
* Populate software module metadata.
|
||||||
*
|
*
|
||||||
* @param distributionSet
|
* @param distributionSet
|
||||||
*/
|
*/
|
||||||
public void populateDSMetadata(final DistributionSet distributionSet) {
|
public void populateDSMetadata(final DistributionSet distributionSet) {
|
||||||
removeAllItems();
|
removeAllItems();
|
||||||
if (null == distributionSet) {
|
if (null == distributionSet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectedDistSetId = distributionSet.getId();
|
selectedDistSetId = distributionSet.getId();
|
||||||
final List<DistributionSetMetadata> dsMetadataList = distributionSet.getMetadata();
|
final List<DistributionSetMetadata> dsMetadataList = distributionSetManagement
|
||||||
|
.findDistributionSetMetadataByDistributionSetId(selectedDistSetId);
|
||||||
if (null != dsMetadataList && !dsMetadataList.isEmpty()) {
|
if (null != dsMetadataList && !dsMetadataList.isEmpty()) {
|
||||||
dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata));
|
dsMetadataList.forEach(dsMetadata -> setDSMetadataProperties(dsMetadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create metadata .
|
|
||||||
*
|
|
||||||
* @param metadataKeyName
|
|
||||||
*/
|
|
||||||
public void createMetadata(final String metadataKeyName){
|
|
||||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
|
||||||
final Item item = metadataContainer.addItem(metadataKeyName);
|
|
||||||
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete metadata.
|
|
||||||
*
|
|
||||||
* @param metadataKeyName
|
|
||||||
*/
|
|
||||||
public void deleteMetadata(final String metadataKeyName){
|
|
||||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
|
||||||
metadataContainer.removeItem(metadataKeyName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDSMetadataTable() {
|
private void createDSMetadataTable() {
|
||||||
@@ -131,9 +109,9 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
|||||||
setContainerDataSource(getDistSetContainer());
|
setContainerDataSource(getDistSetContainer());
|
||||||
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
|
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
|
||||||
addDSMetadataTableHeader();
|
addDSMetadataTableHeader();
|
||||||
setSizeFull();
|
setSizeFull();
|
||||||
//same as height of other tabs in details tabsheet
|
// same as height of other tabs in details tabsheet
|
||||||
setHeight(116,Unit.PIXELS);
|
setHeight(116, Unit.PIXELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndexedContainer getDistSetContainer() {
|
private IndexedContainer getDistSetContainer() {
|
||||||
@@ -141,7 +119,7 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
|||||||
container.addContainerProperty(METADATA_KEY, String.class, "");
|
container.addContainerProperty(METADATA_KEY, String.class, "");
|
||||||
setColumnExpandRatio(METADATA_KEY, 0.7f);
|
setColumnExpandRatio(METADATA_KEY, 0.7f);
|
||||||
setColumnAlignment(METADATA_KEY, Align.LEFT);
|
setColumnAlignment(METADATA_KEY, Align.LEFT);
|
||||||
|
|
||||||
if (permissionChecker.hasUpdateDistributionPermission()) {
|
if (permissionChecker.hasUpdateDistributionPermission()) {
|
||||||
container.addContainerProperty(VIEW, Label.class, "");
|
container.addContainerProperty(VIEW, Label.class, "");
|
||||||
setColumnExpandRatio(VIEW, 0.2F);
|
setColumnExpandRatio(VIEW, 0.2F);
|
||||||
@@ -154,39 +132,36 @@ public class DistributionSetMetadatadetailslayout extends Table{
|
|||||||
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
|
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata) {
|
||||||
private void setDSMetadataProperties(final DistributionSetMetadata dsMetadata){
|
|
||||||
final Item item = getContainerDataSource().addItem(dsMetadata.getKey());
|
final Item item = getContainerDataSource().addItem(dsMetadata.getKey());
|
||||||
item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey());
|
item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCustomGeneratedColumns() {
|
private void addCustomGeneratedColumns() {
|
||||||
addGeneratedColumn(METADATA_KEY,
|
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
||||||
(source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Button customMetadataDetailButton(final String metadataKey) {
|
private Button customMetadataDetailButton(final String metadataKey) {
|
||||||
final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View "
|
final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey,
|
||||||
+ metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
"View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
||||||
viewIcon.setData(metadataKey);
|
viewIcon.setData(metadataKey);
|
||||||
viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
|
viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
|
||||||
+ " " + "text-style");
|
+ " " + "text-style");
|
||||||
viewIcon.addClickListener(event -> showMetadataDetails(selectedDistSetId, metadataKey));
|
viewIcon.addClickListener(event -> showMetadataDetails(selectedDistSetId, metadataKey));
|
||||||
return viewIcon;
|
return viewIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getDetailLinkId(final String name) {
|
private static String getDetailLinkId(final String name) {
|
||||||
return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name)
|
return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name).toString();
|
||||||
.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMetadataDetails(final Long selectedDistSetId , final String metadataKey) {
|
private void showMetadataDetails(final Long selectedDistSetId, final String metadataKey) {
|
||||||
DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId);
|
final DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId);
|
||||||
|
|
||||||
/* display the window */
|
/* display the window */
|
||||||
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(distSet,
|
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(distSet,
|
||||||
entityFactory.generateDistributionSetMetadata(distSet, metadataKey, "") ));
|
entityFactory.generateDistributionSetMetadata(distSet, metadataKey, "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,19 +41,19 @@ import com.vaadin.ui.themes.ValoTheme;
|
|||||||
@ViewScope
|
@ViewScope
|
||||||
public class SoftwareModuleMetadatadetailslayout extends Table {
|
public class SoftwareModuleMetadatadetailslayout extends Table {
|
||||||
|
|
||||||
private static final long serialVersionUID = 2913758299611838818L;
|
private static final long serialVersionUID = 2913758299611838818L;
|
||||||
|
|
||||||
private static final String METADATA_KEY = "Key";
|
private static final String METADATA_KEY = "Key";
|
||||||
|
|
||||||
private SpPermissionChecker permissionChecker;
|
private SpPermissionChecker permissionChecker;
|
||||||
|
|
||||||
private transient SoftwareManagement softwareManagement;
|
private transient SoftwareManagement softwareManagement;
|
||||||
|
|
||||||
private SwMetadataPopupLayout swMetadataPopupLayout;
|
private SwMetadataPopupLayout swMetadataPopupLayout;
|
||||||
|
|
||||||
private I18N i18n;
|
private I18N i18n;
|
||||||
|
|
||||||
private Long selectedSWModuleId;
|
private Long selectedSWModuleId;
|
||||||
|
|
||||||
private transient EntityFactory entityFactory;
|
private transient EntityFactory entityFactory;
|
||||||
|
|
||||||
@@ -83,100 +83,102 @@ public class SoftwareModuleMetadatadetailslayout extends Table {
|
|||||||
addCustomGeneratedColumns();
|
addCustomGeneratedColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate software module metadata table.
|
* Populate software module metadata table.
|
||||||
*
|
*
|
||||||
* @param swModule
|
* @param swModule
|
||||||
*/
|
*/
|
||||||
public void populateSMMetadata(final SoftwareModule swModule) {
|
public void populateSMMetadata(final SoftwareModule swModule) {
|
||||||
removeAllItems();
|
removeAllItems();
|
||||||
if (null == swModule) {
|
if (null == swModule) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
selectedSWModuleId = swModule.getId();
|
selectedSWModuleId = swModule.getId();
|
||||||
final List<SoftwareModuleMetadata> swMetadataList = swModule.getMetadata();
|
final List<SoftwareModuleMetadata> swMetadataList = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(selectedSWModuleId);
|
||||||
if (null != swMetadataList && !swMetadataList.isEmpty()) {
|
if (null != swMetadataList && !swMetadataList.isEmpty()) {
|
||||||
swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata));
|
swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create metadata.
|
* Create metadata.
|
||||||
*
|
*
|
||||||
* @param metadataKeyName
|
* @param metadataKeyName
|
||||||
*/
|
*/
|
||||||
public void createMetadata(final String metadataKeyName) {
|
public void createMetadata(final String metadataKeyName) {
|
||||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||||
final Item item = metadataContainer.addItem(metadataKeyName);
|
final Item item = metadataContainer.addItem(metadataKeyName);
|
||||||
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
|
item.getItemProperty(METADATA_KEY).setValue(metadataKeyName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete metadata.
|
* Delete metadata.
|
||||||
*
|
*
|
||||||
* @param metadataKeyName
|
* @param metadataKeyName
|
||||||
*/
|
*/
|
||||||
public void deleteMetadata(final String metadataKeyName) {
|
public void deleteMetadata(final String metadataKeyName) {
|
||||||
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
final IndexedContainer metadataContainer = (IndexedContainer) getContainerDataSource();
|
||||||
metadataContainer.removeItem(metadataKeyName);
|
metadataContainer.removeItem(metadataKeyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createSWMMetadataTable() {
|
private void createSWMMetadataTable() {
|
||||||
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
|
addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES);
|
||||||
addStyleName(ValoTheme.TABLE_NO_STRIPES);
|
addStyleName(ValoTheme.TABLE_NO_STRIPES);
|
||||||
addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE);
|
addStyleName(SPUIStyleDefinitions.SW_MODULE_TABLE);
|
||||||
setSelectable(false);
|
setSelectable(false);
|
||||||
setImmediate(true);
|
setImmediate(true);
|
||||||
setContainerDataSource(getSwModuleMetadataContainer());
|
setContainerDataSource(getSwModuleMetadataContainer());
|
||||||
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
|
setColumnHeaderMode(ColumnHeaderMode.EXPLICIT);
|
||||||
addSMMetadataTableHeader();
|
addSMMetadataTableHeader();
|
||||||
setSizeFull();
|
setSizeFull();
|
||||||
// same as height of other tabs in details tabsheet
|
//same as height of other tabs in details tabsheet
|
||||||
setHeight(116, Unit.PIXELS);
|
setHeight(116,Unit.PIXELS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndexedContainer getSwModuleMetadataContainer() {
|
private IndexedContainer getSwModuleMetadataContainer() {
|
||||||
final IndexedContainer container = new IndexedContainer();
|
final IndexedContainer container = new IndexedContainer();
|
||||||
container.addContainerProperty(METADATA_KEY, String.class, "");
|
container.addContainerProperty(METADATA_KEY, String.class, "");
|
||||||
setColumnAlignment(METADATA_KEY, Align.LEFT);
|
setColumnAlignment(METADATA_KEY, Align.LEFT);
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSMMetadataTableHeader() {
|
private void addSMMetadataTableHeader() {
|
||||||
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
|
setColumnHeader(METADATA_KEY, i18n.get("header.key"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) {
|
|
||||||
final Item item = getContainerDataSource().addItem(swMetadata.getKey());
|
|
||||||
item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addCustomGeneratedColumns() {
|
private void setSWMetadataProperties(final SoftwareModuleMetadata swMetadata) {
|
||||||
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
final Item item = getContainerDataSource().addItem(swMetadata.getKey());
|
||||||
}
|
item.getItemProperty(METADATA_KEY).setValue(swMetadata.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
private Button customMetadataDetailButton(final String metadataKey) {
|
private void addCustomGeneratedColumns() {
|
||||||
final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey,
|
addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId));
|
||||||
"View" + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
}
|
||||||
viewLink.setData(metadataKey);
|
|
||||||
if (permissionChecker.hasUpdateDistributionPermission()) {
|
|
||||||
viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
|
|
||||||
+ " " + "text-style");
|
|
||||||
viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey));
|
|
||||||
}
|
|
||||||
return viewLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getDetailLinkId(final String name) {
|
private Button customMetadataDetailButton(final String metadataKey) {
|
||||||
return new StringBuilder(SPUIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString();
|
final Button viewLink = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View"
|
||||||
}
|
+ metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class);
|
||||||
|
viewLink.setData(metadataKey);
|
||||||
|
if (permissionChecker.hasUpdateDistributionPermission()) {
|
||||||
|
viewLink.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link"
|
||||||
|
+ " " + "text-style");
|
||||||
|
viewLink.addClickListener(event -> showMetadataDetails(selectedSWModuleId, metadataKey));
|
||||||
|
}
|
||||||
|
return viewLink;
|
||||||
|
}
|
||||||
|
|
||||||
private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) {
|
private static String getDetailLinkId(final String name) {
|
||||||
final SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId);
|
return new StringBuilder(SPUIComponentIdProvider.SW_METADATA_DETAIL_LINK).append('.').append(name).toString();
|
||||||
/* display the window */
|
}
|
||||||
UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule,
|
|
||||||
entityFactory.generateSoftwareModuleMetadata(swmodule, metadataKey, "")));
|
private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) {
|
||||||
}
|
final SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId);
|
||||||
|
/* display the window */
|
||||||
|
UI.getCurrent().addWindow(
|
||||||
|
swMetadataPopupLayout.getWindow(swmodule,
|
||||||
|
entityFactory.generateSoftwareModuleMetadata(swmodule, metadataKey, "")));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.common.filterlayout;
|
package org.eclipse.hawkbit.ui.common.filterlayout;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.ui.utils.SPUIDefinitions.NO_TAG_BUTTON_ID;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -50,7 +52,7 @@ public abstract class AbstractFilterButtons extends Table {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize layout of filter buttons.
|
* Initialize layout of filter buttons.
|
||||||
*
|
*
|
||||||
* @param filterButtonClickBehaviour
|
* @param filterButtonClickBehaviour
|
||||||
* click behaviour of filter buttons.
|
* click behaviour of filter buttons.
|
||||||
*/
|
*/
|
||||||
@@ -95,16 +97,12 @@ public abstract class AbstractFilterButtons extends Table {
|
|||||||
container.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, null, true, true);
|
container.addContainerProperty(SPUILabelDefinitions.VAR_NAME, String.class, null, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
protected void addColumn() {
|
protected void addColumn() {
|
||||||
addGeneratedColumn(FILTER_BUTTON_COLUMN, (source, itemId, columnId) -> addGeneratedCell(itemId));
|
addGeneratedColumn(FILTER_BUTTON_COLUMN, (source, itemId, columnId) -> addGeneratedCell(itemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param itemId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private DragAndDropWrapper addGeneratedCell(final Object itemId) {
|
private DragAndDropWrapper addGeneratedCell(final Object itemId) {
|
||||||
|
|
||||||
final Item item = getItem(itemId);
|
final Item item = getItem(itemId);
|
||||||
final Long id = (Long) item.getItemProperty(SPUILabelDefinitions.VAR_ID).getValue();
|
final Long id = (Long) item.getItemProperty(SPUILabelDefinitions.VAR_ID).getValue();
|
||||||
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
|
final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue();
|
||||||
@@ -116,16 +114,18 @@ public abstract class AbstractFilterButtons extends Table {
|
|||||||
? item.getItemProperty(SPUILabelDefinitions.VAR_COLOR).getValue().toString() : DEFAULT_GREEN;
|
? item.getItemProperty(SPUILabelDefinitions.VAR_COLOR).getValue().toString() : DEFAULT_GREEN;
|
||||||
final Button typeButton = createFilterButton(id, name, desc, color, itemId);
|
final Button typeButton = createFilterButton(id, name, desc, color, itemId);
|
||||||
typeButton.addClickListener(event -> filterButtonClickBehaviour.processFilterButtonClick(event));
|
typeButton.addClickListener(event -> filterButtonClickBehaviour.processFilterButtonClick(event));
|
||||||
if (typeButton.getData().equals(SPUIDefinitions.NO_TAG_BUTTON_ID) && isNoTagSateSelected()) {
|
|
||||||
filterButtonClickBehaviour.setDefaultClickedButton(typeButton);
|
if ((NO_TAG_BUTTON_ID.equals(typeButton.getData()) && isNoTagStateSelected())
|
||||||
} else if (id != null && isClickedByDefault(name)) {
|
|| (id != null && isClickedByDefault(name))) {
|
||||||
|
|
||||||
filterButtonClickBehaviour.setDefaultClickedButton(typeButton);
|
filterButtonClickBehaviour.setDefaultClickedButton(typeButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
return createDragAndDropWrapper(typeButton, name, id);
|
return createDragAndDropWrapper(typeButton, name, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isNoTagSateSelected() {
|
protected boolean isNoTagStateSelected() {
|
||||||
return Boolean.FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DragAndDropWrapper createDragAndDropWrapper(final Button tagButton, final String name, final Long id) {
|
private DragAndDropWrapper createDragAndDropWrapper(final Button tagButton, final String name, final Long id) {
|
||||||
@@ -195,21 +195,21 @@ public abstract class AbstractFilterButtons extends Table {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Id of the buttons table to be used in test cases.
|
* Id of the buttons table to be used in test cases.
|
||||||
*
|
*
|
||||||
* @return Id of the Button table.
|
* @return Id of the Button table.
|
||||||
*/
|
*/
|
||||||
protected abstract String getButtonsTableId();
|
protected abstract String getButtonsTableId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create new lazyquery container to display the buttons.
|
* create new lazyquery container to display the buttons.
|
||||||
*
|
*
|
||||||
* @return reference of {@link LazyQueryContainer}
|
* @return reference of {@link LazyQueryContainer}
|
||||||
*/
|
*/
|
||||||
protected abstract LazyQueryContainer createButtonsLazyQueryContainer();
|
protected abstract LazyQueryContainer createButtonsLazyQueryContainer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if button should be displayed as clicked by default.
|
* Check if button should be displayed as clicked by default.
|
||||||
*
|
*
|
||||||
* @param buttonCaption
|
* @param buttonCaption
|
||||||
* button caption
|
* button caption
|
||||||
* @return true if button is clicked
|
* @return true if button is clicked
|
||||||
@@ -218,7 +218,7 @@ public abstract class AbstractFilterButtons extends Table {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get filter button Id.
|
* Get filter button Id.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@@ -226,7 +226,7 @@ public abstract class AbstractFilterButtons extends Table {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Drop Handler for Filter Buttons.
|
* Get Drop Handler for Filter Buttons.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected abstract DropHandler getFilterButtonDropHandler();
|
protected abstract DropHandler getFilterButtonDropHandler();
|
||||||
@@ -234,14 +234,14 @@ public abstract class AbstractFilterButtons extends Table {
|
|||||||
/**
|
/**
|
||||||
* Get prefix Id of Button Wrapper to be used for drag and drop, delete and
|
* Get prefix Id of Button Wrapper to be used for drag and drop, delete and
|
||||||
* test cases.
|
* test cases.
|
||||||
*
|
*
|
||||||
* @return prefix Id of Button Wrapper
|
* @return prefix Id of Button Wrapper
|
||||||
*/
|
*/
|
||||||
protected abstract String getButttonWrapperIdPrefix();
|
protected abstract String getButttonWrapperIdPrefix();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get info to be set for the button wrapper.
|
* Get info to be set for the button wrapper.
|
||||||
*
|
*
|
||||||
* @return button wrapper info.
|
* @return button wrapper info.
|
||||||
*/
|
*/
|
||||||
protected abstract String getButtonWrapperData();
|
protected abstract String getButtonWrapperData();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
package org.eclipse.hawkbit.ui.common.filterlayout;
|
package org.eclipse.hawkbit.ui.common.filterlayout;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||||
@@ -91,7 +92,7 @@ public abstract class AbstractFilterHeader extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Label createHeaderCaption() {
|
private Label createHeaderCaption() {
|
||||||
return SPUIComponentProvider.getLabel(getTitle(), SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
return new LabelBuilder().name(getTitle()).buildCaptionLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import javax.annotation.PostConstruct;
|
|||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall;
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||||
@@ -215,11 +216,10 @@ public abstract class AbstractDeleteActionsLayout extends VerticalLayout impleme
|
|||||||
if (!hasUnsavedActions()) {
|
if (!hasUnsavedActions()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsavedActionsWindow = SPUIComponentProvider.getWindow(getUnsavedActionsWindowCaption(),
|
unsavedActionsWindow = new WindowBuilder(SPUIDefinitions.CONFIRMATION_WINDOW)
|
||||||
SPUIComponentIdProvider.SAVE_ACTIONS_POPUP, SPUIDefinitions.CONFIRMATION_WINDOW);
|
.caption(getUnsavedActionsWindowCaption()).id(SPUIComponentIdProvider.CONFIRMATION_POPUP_ID)
|
||||||
|
.content(getUnsavedActionsWindowContent()).buildWindow();
|
||||||
unsavedActionsWindow.addCloseListener(event -> unsavedActionsWindowClosed());
|
unsavedActionsWindow.addCloseListener(event -> unsavedActionsWindowClosed());
|
||||||
unsavedActionsWindow.setContent(getUnsavedActionsWindowContent());
|
|
||||||
unsavedActionsWindow.setId(SPUIComponentIdProvider.CONFIRMATION_POPUP_ID);
|
|
||||||
UI.getCurrent().addWindow(unsavedActionsWindow);
|
UI.getCurrent().addWindow(unsavedActionsWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.common.grid;
|
package org.eclipse.hawkbit.ui.common.grid;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import com.vaadin.server.FontAwesome;
|
import com.vaadin.server.FontAwesome;
|
||||||
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
|
||||||
import com.vaadin.ui.Alignment;
|
import com.vaadin.ui.Alignment;
|
||||||
import com.vaadin.ui.Button;
|
import com.vaadin.ui.Button;
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
import com.vaadin.ui.HorizontalLayout;
|
||||||
@@ -61,7 +60,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
|||||||
private void createComponents() {
|
private void createComponents() {
|
||||||
headerCaptionLayout = getHeaderCaptionLayout();
|
headerCaptionLayout = getHeaderCaptionLayout();
|
||||||
if (isRollout()) {
|
if (isRollout()) {
|
||||||
searchField = createSearchField();
|
searchField = new TextFieldBuilder(getSearchBoxId()).createSearchField(event -> searchBy(event.getText()));
|
||||||
searchResetIcon = createSearchResetIcon();
|
searchResetIcon = createSearchResetIcon();
|
||||||
addButton = createAddButton();
|
addButton = createAddButton();
|
||||||
}
|
}
|
||||||
@@ -92,7 +91,7 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
|||||||
addStyleName("no-border-bottom");
|
addStyleName("no-border-bottom");
|
||||||
}
|
}
|
||||||
|
|
||||||
private HorizontalLayout createHeaderFilterIconLayout() {
|
private static HorizontalLayout createHeaderFilterIconLayout() {
|
||||||
final HorizontalLayout titleFilterIconsLayout = new HorizontalLayout();
|
final HorizontalLayout titleFilterIconsLayout = new HorizontalLayout();
|
||||||
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
||||||
titleFilterIconsLayout.setSpacing(false);
|
titleFilterIconsLayout.setSpacing(false);
|
||||||
@@ -101,17 +100,6 @@ public abstract class AbstractGridHeader extends VerticalLayout {
|
|||||||
return titleFilterIconsLayout;
|
return titleFilterIconsLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextField createSearchField() {
|
|
||||||
final TextField textField = SPUIComponentProvider.getTextField("", "filter-box", "text-style filter-box-hide",
|
|
||||||
false, "", "", false, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
textField.setId(getSearchBoxId());
|
|
||||||
textField.setWidth(100.0f, Unit.PERCENTAGE);
|
|
||||||
textField.addTextChangeListener(event -> searchBy(event.getText()));
|
|
||||||
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
|
|
||||||
textField.setTextChangeTimeout(1000);
|
|
||||||
return textField;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SPUIButton createSearchResetIcon() {
|
private SPUIButton createSearchResetIcon() {
|
||||||
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(getSearchRestIconId(), "", "", null,
|
final SPUIButton button = (SPUIButton) SPUIComponentProvider.getButton(getSearchRestIconId(), "", "", null,
|
||||||
false, FontAwesome.SEARCH, SPUIButtonStyleSmallNoBorder.class);
|
false, FontAwesome.SEARCH, SPUIButtonStyleSmallNoBorder.class);
|
||||||
|
|||||||
@@ -12,20 +12,20 @@ import javax.annotation.PostConstruct;
|
|||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.LabelBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
import org.eclipse.hawkbit.ui.components.SPUIButton;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
import org.eclipse.hawkbit.ui.utils.I18N;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.vaadin.spring.events.EventBus;
|
import org.vaadin.spring.events.EventBus;
|
||||||
|
|
||||||
import com.vaadin.event.dd.DropHandler;
|
import com.vaadin.event.dd.DropHandler;
|
||||||
import com.vaadin.server.FontAwesome;
|
import com.vaadin.server.FontAwesome;
|
||||||
import com.vaadin.ui.AbstractTextField.TextChangeEventMode;
|
|
||||||
import com.vaadin.ui.Alignment;
|
import com.vaadin.ui.Alignment;
|
||||||
import com.vaadin.ui.Button;
|
import com.vaadin.ui.Button;
|
||||||
import com.vaadin.ui.DragAndDropWrapper;
|
import com.vaadin.ui.DragAndDropWrapper;
|
||||||
@@ -86,7 +86,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
|||||||
|
|
||||||
private void createComponents() {
|
private void createComponents() {
|
||||||
headerCaption = createHeaderCaption();
|
headerCaption = createHeaderCaption();
|
||||||
searchField = createSearchField();
|
searchField = new TextFieldBuilder(getSearchBoxId()).createSearchField(event -> searchBy(event.getText()));
|
||||||
|
|
||||||
searchResetIcon = createSearchResetIcon();
|
searchResetIcon = createSearchResetIcon();
|
||||||
|
|
||||||
@@ -203,21 +203,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Label createHeaderCaption() {
|
private Label createHeaderCaption() {
|
||||||
final Label captionLabel = SPUIComponentProvider.getLabel(getHeaderCaption(),
|
return new LabelBuilder().name(getHeaderCaption()).buildCaptionLabel();
|
||||||
SPUILabelDefinitions.SP_WIDGET_CAPTION);
|
|
||||||
return captionLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TextField createSearchField() {
|
|
||||||
final TextField textField = SPUIComponentProvider.getTextField("", "filter-box", "text-style filter-box-hide",
|
|
||||||
false, "", "", false, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
textField.setId(getSearchBoxId());
|
|
||||||
textField.setWidth(100.0f, Unit.PERCENTAGE);
|
|
||||||
textField.addTextChangeListener(event -> searchBy(event.getText()));
|
|
||||||
textField.setTextChangeEventMode(TextChangeEventMode.LAZY);
|
|
||||||
// 1 seconds timeout.
|
|
||||||
textField.setTextChangeTimeout(1000);
|
|
||||||
return textField;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SPUIButton createSearchResetIcon() {
|
private SPUIButton createSearchResetIcon() {
|
||||||
@@ -322,7 +308,7 @@ public abstract class AbstractTableHeader extends VerticalLayout {
|
|||||||
maxMinIcon.setData(Boolean.FALSE);
|
maxMinIcon.setData(Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private HorizontalLayout createHeaderFilterIconLayout() {
|
private static HorizontalLayout createHeaderFilterIconLayout() {
|
||||||
final HorizontalLayout titleFilterIconsLayout = new HorizontalLayout();
|
final HorizontalLayout titleFilterIconsLayout = new HorizontalLayout();
|
||||||
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
titleFilterIconsLayout.addStyleName(SPUIStyleDefinitions.WIDGET_TITLE);
|
||||||
titleFilterIconsLayout.setSpacing(false);
|
titleFilterIconsLayout.setSpacing(false);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import com.vaadin.ui.VerticalLayout;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attributes Vertical layout for Target.
|
* Attributes Vertical layout for Target.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -30,10 +30,10 @@ public class SPTargetAttributesLayout {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Parametric constructor.
|
* Parametric constructor.
|
||||||
*
|
*
|
||||||
* @param controllerAttibs
|
* @param controllerAttibs
|
||||||
* controller attributes
|
* controller attributes
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public SPTargetAttributesLayout(final Map<String, String> controllerAttibs) {
|
public SPTargetAttributesLayout(final Map<String, String> controllerAttibs) {
|
||||||
targetAttributesLayout = new VerticalLayout();
|
targetAttributesLayout = new VerticalLayout();
|
||||||
@@ -44,7 +44,7 @@ public class SPTargetAttributesLayout {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom Decorate.
|
* Custom Decorate.
|
||||||
*
|
*
|
||||||
* @param controllerAttibs
|
* @param controllerAttibs
|
||||||
*/
|
*/
|
||||||
private void decorate(final Map<String, String> controllerAttibs) {
|
private void decorate(final Map<String, String> controllerAttibs) {
|
||||||
@@ -52,7 +52,7 @@ public class SPTargetAttributesLayout {
|
|||||||
final Label title = new Label(i18n.get("label.target.controller.attrs"), ContentMode.HTML);
|
final Label title = new Label(i18n.get("label.target.controller.attrs"), ContentMode.HTML);
|
||||||
title.addStyleName(SPUIDefinitions.TEXT_STYLE);
|
title.addStyleName(SPUIDefinitions.TEXT_STYLE);
|
||||||
targetAttributesLayout.addComponent(title);
|
targetAttributesLayout.addComponent(title);
|
||||||
if (HawkbitCommonUtil.mapCheckStrings(controllerAttibs)) {
|
if (HawkbitCommonUtil.isNotNullOrEmpty(controllerAttibs)) {
|
||||||
for (final Map.Entry<String, String> entry : controllerAttibs.entrySet()) {
|
for (final Map.Entry<String, String> entry : controllerAttibs.entrySet()) {
|
||||||
targetAttributesLayout.addComponent(
|
targetAttributesLayout.addComponent(
|
||||||
SPUIComponentProvider.createNameValueLabel(entry.getKey() + ": ", entry.getValue()));
|
SPUIComponentProvider.createNameValueLabel(entry.getKey() + ": ", entry.getValue()));
|
||||||
@@ -62,7 +62,7 @@ public class SPTargetAttributesLayout {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* GET Target Attributes Layout.
|
* GET Target Attributes Layout.
|
||||||
*
|
*
|
||||||
* @return VerticalLayout as UI
|
* @return VerticalLayout as UI
|
||||||
*/
|
*/
|
||||||
public VerticalLayout getTargetAttributesLayout() {
|
public VerticalLayout getTargetAttributesLayout() {
|
||||||
|
|||||||
@@ -17,11 +17,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
|||||||
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
import org.eclipse.hawkbit.ui.common.UserDetailsFormatter;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator;
|
import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator;
|
||||||
import org.eclipse.hawkbit.ui.decorators.HeaderLayoutDecorator;
|
|
||||||
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.I18N;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -34,15 +29,11 @@ import com.vaadin.shared.ui.label.ContentMode;
|
|||||||
import com.vaadin.ui.Button;
|
import com.vaadin.ui.Button;
|
||||||
import com.vaadin.ui.CheckBox;
|
import com.vaadin.ui.CheckBox;
|
||||||
import com.vaadin.ui.ComboBox;
|
import com.vaadin.ui.ComboBox;
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
|
||||||
import com.vaadin.ui.Label;
|
import com.vaadin.ui.Label;
|
||||||
import com.vaadin.ui.Link;
|
import com.vaadin.ui.Link;
|
||||||
import com.vaadin.ui.Panel;
|
import com.vaadin.ui.Panel;
|
||||||
import com.vaadin.ui.TabSheet;
|
import com.vaadin.ui.TabSheet;
|
||||||
import com.vaadin.ui.TextArea;
|
|
||||||
import com.vaadin.ui.TextField;
|
|
||||||
import com.vaadin.ui.VerticalLayout;
|
import com.vaadin.ui.VerticalLayout;
|
||||||
import com.vaadin.ui.Window;
|
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,152 +52,9 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param className
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static HorizontalLayout getHorizontalLayout(final Class<? extends HorizontalLayout> className) {
|
|
||||||
HorizontalLayout hLayout = null;
|
|
||||||
try {
|
|
||||||
|
|
||||||
hLayout = className.newInstance();
|
|
||||||
} catch (final InstantiationException exception) {
|
|
||||||
LOG.error("Error occured while creating HorizontalLayout-" + className, exception);
|
|
||||||
} catch (final IllegalAccessException exception) {
|
|
||||||
LOG.error("Error occured while acessing HorizontalLayout-" + className, exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get HorizontalLayout UI component.
|
|
||||||
*
|
|
||||||
* @param className
|
|
||||||
* as Layout
|
|
||||||
* @return HorizontalLayout as UI
|
|
||||||
*/
|
|
||||||
public static HorizontalLayout getHorizontalLayout() {
|
|
||||||
HorizontalLayout hLayout = null;
|
|
||||||
try {
|
|
||||||
hLayout = HorizontalLayout.class.newInstance();
|
|
||||||
} catch (final InstantiationException exception) {
|
|
||||||
LOG.error("Error occured while creating HorizontalLayout-", exception);
|
|
||||||
} catch (final IllegalAccessException exception) {
|
|
||||||
LOG.error("Error occured while acessing HorizontalLayout-", exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param tableHeaderLayoutDecorator
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static HorizontalLayout getHeaderLayout(
|
|
||||||
final Class<? extends HeaderLayoutDecorator> tableHeaderLayoutDecorator) {
|
|
||||||
// Do we really need this???
|
|
||||||
HorizontalLayout hLayout = getHorizontalLayout(new SPUIHorizontalLayout().getUiHorizontalLayout().getClass());
|
|
||||||
|
|
||||||
if (tableHeaderLayoutDecorator == null) {
|
|
||||||
return hLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final HeaderLayoutDecorator layoutDecorator = tableHeaderLayoutDecorator.newInstance();
|
|
||||||
hLayout = layoutDecorator.decorate(hLayout);
|
|
||||||
|
|
||||||
} catch (final InstantiationException | IllegalAccessException exception) {
|
|
||||||
LOG.error("Error occured while creating horizontal decorator " + HeaderLayoutDecorator.class,
|
|
||||||
exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hLayout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Label UI component.
|
* Get Label UI component.
|
||||||
*
|
*
|
||||||
* @param name
|
|
||||||
* label caption
|
|
||||||
* @param type
|
|
||||||
* string simple|Confirm|Message
|
|
||||||
* @return Label
|
|
||||||
*/
|
|
||||||
public static Label getLabel(final String name, final String type) {
|
|
||||||
return SPUILabelDecorator.getDeocratedLabel(name, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get window component.
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* window caption
|
|
||||||
* @param id
|
|
||||||
* window id
|
|
||||||
* @param type
|
|
||||||
* type of window
|
|
||||||
* @return Window
|
|
||||||
*/
|
|
||||||
public static Window getWindow(final String caption, final String id, final String type) {
|
|
||||||
return SPUIWindowDecorator.getDeocratedWindow(caption, id, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Label UI component.
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* set the caption of the textfield
|
|
||||||
* @param style
|
|
||||||
* set style
|
|
||||||
* @param styleName
|
|
||||||
* add style
|
|
||||||
* @param required
|
|
||||||
* to set field as mandatory
|
|
||||||
* @param data
|
|
||||||
* component data
|
|
||||||
* @param prompt
|
|
||||||
* prompt user for input
|
|
||||||
* @param immediate
|
|
||||||
* set component's immediate mode specified mode
|
|
||||||
* @param maxLengthAllowed
|
|
||||||
* maximum characters allowed
|
|
||||||
* @return TextField text field
|
|
||||||
*/
|
|
||||||
public static TextField getTextField(final String caption, final String style, final String styleName,
|
|
||||||
final boolean required, final String data, final String prompt, final boolean immediate,
|
|
||||||
final int maxLengthAllowed) {
|
|
||||||
return SPUITextFieldDecorator.decorate(caption, style, styleName, required, data, prompt, immediate,
|
|
||||||
maxLengthAllowed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Label UI component. *
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* set the caption of the textArea
|
|
||||||
* @param style
|
|
||||||
* set style
|
|
||||||
* @param styleName
|
|
||||||
* add style
|
|
||||||
* @param required
|
|
||||||
* to set field as mandatory
|
|
||||||
* @param data
|
|
||||||
* component data
|
|
||||||
* @param promt
|
|
||||||
* prompt user for input
|
|
||||||
* @param maxLength
|
|
||||||
* maximum characters allowed
|
|
||||||
* @return TextArea text area
|
|
||||||
*/
|
|
||||||
public static TextArea getTextArea(final String caption, final String style, final String styleName,
|
|
||||||
final boolean required, final String data, final String promt, final int maxLength) {
|
|
||||||
return SPUITextAreaDecorator.decorate(caption, style, styleName, required, data, promt, maxLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Label UI component.
|
|
||||||
*
|
|
||||||
* @param caption
|
* @param caption
|
||||||
* caption of the combo box
|
* caption of the combo box
|
||||||
* @param height
|
* @param height
|
||||||
@@ -252,7 +100,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Button - Factory Approach for decoration.
|
* Get Button - Factory Approach for decoration.
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* as string
|
* as string
|
||||||
* @param buttonName
|
* @param buttonName
|
||||||
@@ -289,7 +137,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the style required.
|
* Get the style required.
|
||||||
*
|
*
|
||||||
* @return String
|
* @return String
|
||||||
*/
|
*/
|
||||||
public static String getPinButtonStyle() {
|
public static String getPinButtonStyle() {
|
||||||
@@ -305,7 +153,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get DistributionSet Info Panel.
|
* Get DistributionSet Info Panel.
|
||||||
*
|
*
|
||||||
* @param distributionSet
|
* @param distributionSet
|
||||||
* as DistributionSet
|
* as DistributionSet
|
||||||
* @param caption
|
* @param caption
|
||||||
@@ -323,7 +171,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to CreateName value labels.
|
* Method to CreateName value labels.
|
||||||
*
|
*
|
||||||
* @param label
|
* @param label
|
||||||
* as string
|
* as string
|
||||||
* @param values
|
* @param values
|
||||||
@@ -356,7 +204,7 @@ public final class SPUIComponentProvider {
|
|||||||
/**
|
/**
|
||||||
* Create label which represents the {@link BaseEntity#getCreatedBy()} by
|
* Create label which represents the {@link BaseEntity#getCreatedBy()} by
|
||||||
* user name
|
* user name
|
||||||
*
|
*
|
||||||
* @param i18n
|
* @param i18n
|
||||||
* the i18n
|
* the i18n
|
||||||
* @param baseEntity
|
* @param baseEntity
|
||||||
@@ -371,7 +219,7 @@ public final class SPUIComponentProvider {
|
|||||||
/**
|
/**
|
||||||
* Create label which represents the
|
* Create label which represents the
|
||||||
* {@link BaseEntity#getLastModifiedBy()()} by user name
|
* {@link BaseEntity#getLastModifiedBy()()} by user name
|
||||||
*
|
*
|
||||||
* @param i18n
|
* @param i18n
|
||||||
* the i18n
|
* the i18n
|
||||||
* @param baseEntity
|
* @param baseEntity
|
||||||
@@ -385,7 +233,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Bold Text.
|
* Get Bold Text.
|
||||||
*
|
*
|
||||||
* @param text
|
* @param text
|
||||||
* as String
|
* as String
|
||||||
* @return String as bold
|
* @return String as bold
|
||||||
@@ -396,7 +244,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the layout for Target:Controller Attributes.
|
* Get the layout for Target:Controller Attributes.
|
||||||
*
|
*
|
||||||
* @param controllerAttibs
|
* @param controllerAttibs
|
||||||
* as Map
|
* as Map
|
||||||
* @return VerticalLayout
|
* @return VerticalLayout
|
||||||
@@ -407,7 +255,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Tabsheet.
|
* Get Tabsheet.
|
||||||
*
|
*
|
||||||
* @return SPUITabSheet
|
* @return SPUITabSheet
|
||||||
*/
|
*/
|
||||||
public static TabSheet getDetailsTabSheet() {
|
public static TabSheet getDetailsTabSheet() {
|
||||||
@@ -416,7 +264,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Layout of tabs in detail tabsheet.
|
* Layout of tabs in detail tabsheet.
|
||||||
*
|
*
|
||||||
* @return VerticalLayout
|
* @return VerticalLayout
|
||||||
*/
|
*/
|
||||||
public static VerticalLayout getDetailTabLayout() {
|
public static VerticalLayout getDetailTabLayout() {
|
||||||
@@ -429,7 +277,7 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a link.
|
* Method to create a link.
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
* of the link
|
* of the link
|
||||||
* @param name
|
* @param name
|
||||||
@@ -465,10 +313,10 @@ public final class SPUIComponentProvider {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates help/documentation links from within management UI.
|
* Generates help/documentation links from within management UI.
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param uri
|
||||||
* to documentation site
|
* to documentation site
|
||||||
*
|
*
|
||||||
* @return generated link
|
* @return generated link
|
||||||
*/
|
*/
|
||||||
public static Link getHelpLink(final String uri) {
|
public static Link getHelpLink(final String uri) {
|
||||||
|
|||||||
@@ -1,49 +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.components;
|
|
||||||
|
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plain Horizontal Layout.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class SPUIHorizontalLayout {
|
|
||||||
private final HorizontalLayout uiHorizontalLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default constructor.
|
|
||||||
*/
|
|
||||||
public SPUIHorizontalLayout() {
|
|
||||||
uiHorizontalLayout = new HorizontalLayout();
|
|
||||||
decorate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorate.
|
|
||||||
*/
|
|
||||||
private void decorate() {
|
|
||||||
uiHorizontalLayout.setImmediate(false);
|
|
||||||
uiHorizontalLayout.setMargin(false);
|
|
||||||
uiHorizontalLayout.setSpacing(true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get HorizontalLayout.
|
|
||||||
*
|
|
||||||
* @return HorizontalLayout as UI
|
|
||||||
*/
|
|
||||||
public HorizontalLayout getUiHorizontalLayout() {
|
|
||||||
return uiHorizontalLayout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,21 +17,22 @@ import com.vaadin.client.renderers.ClickableRenderer.RendererClickHandler;
|
|||||||
import com.vaadin.shared.ui.Connect;
|
import com.vaadin.shared.ui.Connect;
|
||||||
|
|
||||||
import elemental.json.JsonObject;
|
import elemental.json.JsonObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A connector for {@link CustomObjectRenderer }.
|
* A connector for {@link CustomObjectRenderer }.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer.class)
|
@Connect(org.eclipse.hawkbit.ui.customrenderers.renderers.RolloutRenderer.class)
|
||||||
public class RolloutRendererConnector extends ClickableRendererConnector<RolloutRendererData> {
|
public class RolloutRendererConnector extends ClickableRendererConnector<RolloutRendererData> {
|
||||||
private static final long serialVersionUID = 7734682321931830566L;
|
private static final long serialVersionUID = 7734682321931830566L;
|
||||||
|
|
||||||
public org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer getRenderer() {
|
@Override
|
||||||
return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer) super.getRenderer();
|
public org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer getRenderer() {
|
||||||
}
|
return (org.eclipse.hawkbit.ui.customrenderers.client.renderers.RolloutRenderer) super.getRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HandlerRegistration addClickHandler(
|
protected HandlerRegistration addClickHandler(final RendererClickHandler<JsonObject> handler) {
|
||||||
RendererClickHandler<JsonObject> handler) {
|
|
||||||
return getRenderer().addClickHandler(handler);
|
return getRenderer().addClickHandler(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,52 +11,49 @@ package org.eclipse.hawkbit.ui.customrenderers.client.renderers;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RendererData class with Name and Status.
|
* RendererData class with name and status.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RolloutRendererData implements Serializable {
|
public class RolloutRendererData implements Serializable {
|
||||||
private static final long serialVersionUID = -5018181529953620263L;
|
|
||||||
|
|
||||||
private String name;
|
private static final long serialVersionUID = -5018181529953620263L;
|
||||||
|
|
||||||
private String status;
|
private String name;
|
||||||
|
|
||||||
/**
|
private String status;
|
||||||
* Initialize the RendererData.
|
|
||||||
*/
|
|
||||||
public RolloutRendererData() {
|
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Initialize the RendererData empty.
|
||||||
|
*/
|
||||||
|
public RolloutRendererData() {
|
||||||
|
// Needed by Vaadin for compiling the widget set.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the RendererData.
|
* Initialize the RendererData.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* Name of the Rollout.
|
* Name of the Rollout.
|
||||||
* @param status
|
* @param status
|
||||||
* Status of Rollout.
|
* Status of Rollout.
|
||||||
*/
|
*/
|
||||||
public RolloutRendererData(String name, String status) {
|
public RolloutRendererData(final String name, final String status) {
|
||||||
super();
|
this.name = name;
|
||||||
this.name = name;
|
this.status = status;
|
||||||
this.status = status;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(final String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatus() {
|
public String getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatus(String status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public void setStatus(final String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,46 +16,44 @@ import com.vaadin.ui.renderers.ClickableRenderer;
|
|||||||
import elemental.json.JsonValue;
|
import elemental.json.JsonValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders button with provided CustomObject.
|
* Renders button with provided CustomObject. Used to display button with link.
|
||||||
* Used to display button with link.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RolloutRenderer extends ClickableRenderer<RolloutRendererData> {
|
public class RolloutRenderer extends ClickableRenderer<RolloutRendererData> {
|
||||||
|
|
||||||
private static final long serialVersionUID = -8754180585906263554L;
|
private static final long serialVersionUID = -8754180585906263554L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new custom object renderer.
|
* Creates a new custom object renderer.
|
||||||
*/
|
*/
|
||||||
public RolloutRenderer() {
|
public RolloutRenderer() {
|
||||||
super(RolloutRendererData.class, null);
|
super(RolloutRendererData.class, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize custom object renderer with {@link Class<CustomObject>}
|
|
||||||
*
|
|
||||||
* @param presentationType
|
|
||||||
* Class<CustomObject>
|
|
||||||
*/
|
|
||||||
|
|
||||||
public RolloutRenderer(Class<RolloutRendererData> presentationType) {
|
/**
|
||||||
super(presentationType);
|
* Initialize custom object renderer with the given type.
|
||||||
}
|
*
|
||||||
|
* @param presentationType
|
||||||
|
* Class<CustomObject>
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
public RolloutRenderer(final Class<RolloutRendererData> presentationType) {
|
||||||
* Creates a new custom object renderer and adds the given click listener to it.
|
super(presentationType);
|
||||||
*
|
}
|
||||||
* @param listener
|
|
||||||
* the click listener to register
|
|
||||||
*/
|
|
||||||
public RolloutRenderer(RendererClickListener listener) {
|
|
||||||
this();
|
|
||||||
addClickListener(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public JsonValue encode(RolloutRendererData resource) {
|
* Creates a new custom object renderer and adds the given click listener to
|
||||||
return super.encode(resource, RolloutRendererData.class);
|
* it.
|
||||||
}
|
*
|
||||||
|
* @param listener
|
||||||
|
* the click listener to register
|
||||||
|
*/
|
||||||
|
public RolloutRenderer(final RendererClickListener listener) {
|
||||||
|
this();
|
||||||
|
addClickListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonValue encode(final RolloutRendererData resource) {
|
||||||
|
return super.encode(resource, RolloutRendererData.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +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.decorators;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
|
||||||
|
|
||||||
import com.vaadin.shared.ui.label.ContentMode;
|
|
||||||
import com.vaadin.ui.Label;
|
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple Decorator for the label.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class SPUILabelDecorator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private Constructor.
|
|
||||||
*/
|
|
||||||
private SPUILabelDecorator() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple decorator.
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* as String
|
|
||||||
* @param type
|
|
||||||
* as String
|
|
||||||
* @return Label
|
|
||||||
*/
|
|
||||||
public static Label getDeocratedLabel(final String name, final String type) {
|
|
||||||
final Label spUILabel = new Label(name);
|
|
||||||
// Set style.
|
|
||||||
final StringBuilder style = new StringBuilder(ValoTheme.LABEL_SMALL);
|
|
||||||
style.append(' ');
|
|
||||||
style.append(ValoTheme.LABEL_BOLD);
|
|
||||||
spUILabel.addStyleName(style.toString());
|
|
||||||
if (SPUILabelDefinitions.SP_WIDGET_CAPTION.equalsIgnoreCase(type)) {
|
|
||||||
spUILabel.setValue(name);
|
|
||||||
spUILabel.addStyleName("header-caption");
|
|
||||||
} else if (SPUILabelDefinitions.SP_LABEL_MESSAGE.equalsIgnoreCase(type)) {
|
|
||||||
spUILabel.setContentMode(ContentMode.HTML);
|
|
||||||
spUILabel.addStyleName(SPUILabelDefinitions.SP_LABEL_MESSAGE_STYLE);
|
|
||||||
} else {
|
|
||||||
spUILabel.setImmediate(false);
|
|
||||||
spUILabel.setWidth("-1px");
|
|
||||||
spUILabel.setHeight("-1px");
|
|
||||||
}
|
|
||||||
|
|
||||||
return spUILabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,81 +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.decorators;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.vaadin.ui.TextArea;
|
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TextArea with required style.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class SPUITextAreaDecorator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private Constrcutor.
|
|
||||||
*/
|
|
||||||
private SPUITextAreaDecorator() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorate.
|
|
||||||
*
|
|
||||||
* @param style
|
|
||||||
* set style
|
|
||||||
* @param styleName
|
|
||||||
* add style
|
|
||||||
* @param required
|
|
||||||
* to set field as mandatory
|
|
||||||
* @param data
|
|
||||||
* component data
|
|
||||||
* @param prompt
|
|
||||||
* as user for input
|
|
||||||
* @param maxLength
|
|
||||||
* maximum characters allowed
|
|
||||||
* @return TextArea as comp
|
|
||||||
*/
|
|
||||||
public static TextArea decorate(final String caption, final String style, final String styleName,
|
|
||||||
final boolean required, final String data, final String prompt, final int maxLength) {
|
|
||||||
final TextArea spUITxtArea = new TextArea();
|
|
||||||
// Default settings
|
|
||||||
spUITxtArea.setRequired(false);
|
|
||||||
spUITxtArea.addStyleName(ValoTheme.TEXTAREA_SMALL);
|
|
||||||
if (StringUtils.isNotEmpty(caption)) {
|
|
||||||
spUITxtArea.setCaption(caption);
|
|
||||||
}
|
|
||||||
if (required) {
|
|
||||||
spUITxtArea.setRequired(true);
|
|
||||||
}
|
|
||||||
// Add style
|
|
||||||
if (StringUtils.isNotEmpty(style)) {
|
|
||||||
spUITxtArea.setStyleName(style);
|
|
||||||
}
|
|
||||||
// Add style Name
|
|
||||||
if (StringUtils.isNotEmpty(styleName)) {
|
|
||||||
spUITxtArea.addStyleName(styleName);
|
|
||||||
}
|
|
||||||
if (StringUtils.isNotEmpty(prompt)) {
|
|
||||||
spUITxtArea.setInputPrompt(prompt);
|
|
||||||
}
|
|
||||||
if (StringUtils.isNotEmpty(data)) {
|
|
||||||
spUITxtArea.setData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxLength > 0) {
|
|
||||||
spUITxtArea.setMaxLength(maxLength);
|
|
||||||
}
|
|
||||||
return spUITxtArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,88 +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.decorators;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.vaadin.ui.TextField;
|
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorate TextField with required style.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class SPUITextFieldDecorator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*/
|
|
||||||
private SPUITextFieldDecorator() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* set the caption of the textfield
|
|
||||||
* @param style
|
|
||||||
* set style
|
|
||||||
* @param styleName
|
|
||||||
* add style
|
|
||||||
* @param required
|
|
||||||
* to set field as mandatory
|
|
||||||
* @param data
|
|
||||||
* component data
|
|
||||||
* @param prompt
|
|
||||||
* prompt user for input
|
|
||||||
* @param immediate
|
|
||||||
* as for display
|
|
||||||
* @param maxLengthAllowed
|
|
||||||
* maximum characters allowed
|
|
||||||
* @return Text field as decorated
|
|
||||||
*/
|
|
||||||
public static TextField decorate(final String caption, final String style, final String styleName,
|
|
||||||
final boolean required, final String data, final String prompt, final boolean immediate,
|
|
||||||
final int maxLengthAllowed) {
|
|
||||||
final TextField spUITxtFld = new TextField();
|
|
||||||
if (StringUtils.isNotEmpty(caption)) {
|
|
||||||
spUITxtFld.setCaption(caption);
|
|
||||||
}
|
|
||||||
// Default settings
|
|
||||||
spUITxtFld.setRequired(false);
|
|
||||||
spUITxtFld.addStyleName(ValoTheme.TEXTFIELD_SMALL);
|
|
||||||
if (required) {
|
|
||||||
spUITxtFld.setRequired(true);
|
|
||||||
}
|
|
||||||
if (immediate) {
|
|
||||||
spUITxtFld.setImmediate(true);
|
|
||||||
}
|
|
||||||
// Add style
|
|
||||||
if (StringUtils.isNotEmpty(style)) {
|
|
||||||
spUITxtFld.setStyleName(style);
|
|
||||||
}
|
|
||||||
// Add style Name
|
|
||||||
if (StringUtils.isNotEmpty(styleName)) {
|
|
||||||
spUITxtFld.addStyleName(styleName);
|
|
||||||
}
|
|
||||||
if (StringUtils.isNotEmpty(prompt)) {
|
|
||||||
spUITxtFld.setInputPrompt(prompt);
|
|
||||||
}
|
|
||||||
if (StringUtils.isNotEmpty(data)) {
|
|
||||||
spUITxtFld.setData(data);
|
|
||||||
}
|
|
||||||
if (maxLengthAllowed > 0) {
|
|
||||||
spUITxtFld.setMaxLength(maxLengthAllowed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return spUITxtFld;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,108 +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.decorators;
|
|
||||||
|
|
||||||
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
|
|
||||||
import org.eclipse.hawkbit.ui.common.CustomCommonDialogWindow;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.I18N;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
|
||||||
|
|
||||||
import com.vaadin.ui.AbstractLayout;
|
|
||||||
import com.vaadin.ui.Button.ClickListener;
|
|
||||||
import com.vaadin.ui.Component;
|
|
||||||
import com.vaadin.ui.Window;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorator for Window.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class SPUIWindowDecorator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private Constructor.
|
|
||||||
*/
|
|
||||||
private SPUIWindowDecorator() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorates window based on type.
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* window caption
|
|
||||||
* @param id
|
|
||||||
* window id
|
|
||||||
* @param type
|
|
||||||
* window type
|
|
||||||
* @return Window
|
|
||||||
*/
|
|
||||||
public static CommonDialogWindow getWindow(final String caption, final String id, final String type,
|
|
||||||
final Component content, final ClickListener saveButtonClickListener,
|
|
||||||
final ClickListener cancelButtonClickListener, final String helpLink, final AbstractLayout layout,
|
|
||||||
final I18N i18n) {
|
|
||||||
CommonDialogWindow window = null;
|
|
||||||
if (SPUIDefinitions.CUSTOM_METADATA_WINDOW.equals(type)) {
|
|
||||||
window = new CustomCommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
|
|
||||||
cancelButtonClickListener, layout, i18n);
|
|
||||||
window.setDraggable(true);
|
|
||||||
window.setClosable(true);
|
|
||||||
} else {
|
|
||||||
window = new CommonDialogWindow(caption, content, helpLink, saveButtonClickListener,
|
|
||||||
cancelButtonClickListener, layout, i18n);
|
|
||||||
if (null != id) {
|
|
||||||
window.setId(id);
|
|
||||||
}
|
|
||||||
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) {
|
|
||||||
window.setDraggable(false);
|
|
||||||
window.setClosable(true);
|
|
||||||
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
|
|
||||||
|
|
||||||
} else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
|
||||||
window.setDraggable(true);
|
|
||||||
window.setClosable(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorates window based on type.
|
|
||||||
*
|
|
||||||
* @param caption
|
|
||||||
* window caption
|
|
||||||
* @param id
|
|
||||||
* window id
|
|
||||||
* @param type
|
|
||||||
* window type
|
|
||||||
* @return Window
|
|
||||||
*/
|
|
||||||
public static Window getDeocratedWindow(final String caption, final String id, final String type) {
|
|
||||||
final Window window = new Window(caption);
|
|
||||||
window.setSizeUndefined();
|
|
||||||
window.setModal(true);
|
|
||||||
window.setResizable(false);
|
|
||||||
if (null != id) {
|
|
||||||
window.setId(id);
|
|
||||||
}
|
|
||||||
if (SPUIDefinitions.CONFIRMATION_WINDOW.equals(type)) {
|
|
||||||
window.setDraggable(false);
|
|
||||||
window.setClosable(true);
|
|
||||||
window.addStyleName(SPUIStyleDefinitions.CONFIRMATION_WINDOW_CAPTION);
|
|
||||||
|
|
||||||
} else if (SPUIDefinitions.CREATE_UPDATE_WINDOW.equals(type)) {
|
|
||||||
window.setDraggable(true);
|
|
||||||
window.setClosable(false);
|
|
||||||
}
|
|
||||||
return window;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,6 +18,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
|||||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||||
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
|
import org.eclipse.hawkbit.ui.colorpicker.ColorPickerHelper;
|
||||||
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
|
import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextAreaBuilder;
|
||||||
|
import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
|
import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent;
|
||||||
@@ -45,6 +47,7 @@ import com.vaadin.ui.CheckBox;
|
|||||||
import com.vaadin.ui.Component;
|
import com.vaadin.ui.Component;
|
||||||
import com.vaadin.ui.HorizontalLayout;
|
import com.vaadin.ui.HorizontalLayout;
|
||||||
import com.vaadin.ui.Table;
|
import com.vaadin.ui.Table;
|
||||||
|
import com.vaadin.ui.TextField;
|
||||||
import com.vaadin.ui.VerticalLayout;
|
import com.vaadin.ui.VerticalLayout;
|
||||||
import com.vaadin.ui.themes.ValoTheme;
|
import com.vaadin.ui.themes.ValoTheme;
|
||||||
|
|
||||||
@@ -84,24 +87,24 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout {
|
|||||||
|
|
||||||
super.createRequiredComponents();
|
super.createRequiredComponents();
|
||||||
|
|
||||||
tagName = SPUIComponentProvider.getTextField(i18n.get("textfield.name"), "",
|
tagName = createTextField("textfield.name", SPUIDefinitions.DIST_SET_TYPE_NAME,
|
||||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_NAME, true, "",
|
SPUIDefinitions.NEW_DISTRIBUTION_TYPE_NAME);
|
||||||
i18n.get("textfield.name"), true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
tagName.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_NAME);
|
|
||||||
|
|
||||||
typeKey = SPUIComponentProvider.getTextField(i18n.get("textfield.key"), "",
|
typeKey = createTextField("textfield.key", SPUIDefinitions.DIST_SET_TYPE_KEY,
|
||||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_KEY, true, "", i18n.get("textfield.key"),
|
SPUIDefinitions.NEW_DISTRIBUTION_TYPE_KEY);
|
||||||
true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
|
|
||||||
typeKey.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_KEY);
|
|
||||||
|
|
||||||
tagDesc = SPUIComponentProvider.getTextArea(i18n.get("textfield.description"), "",
|
tagDesc = new TextAreaBuilder().caption(i18n.get("textfield.description"))
|
||||||
ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC, false, "",
|
.styleName(ValoTheme.TEXTFIELD_TINY + " " + SPUIDefinitions.DIST_SET_TYPE_DESC)
|
||||||
i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
|
.prompt(i18n.get("textfield.description")).immediate(true)
|
||||||
tagDesc.setId(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC);
|
.id(SPUIDefinitions.NEW_DISTRIBUTION_TYPE_DESC).buildTextComponent();
|
||||||
tagDesc.setImmediate(true);
|
|
||||||
tagDesc.setNullRepresentation("");
|
tagDesc.setNullRepresentation("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TextField createTextField(final String in18Key, final String styleName, final String id) {
|
||||||
|
return new TextFieldBuilder().caption(i18n.get(in18Key)).styleName(ValoTheme.TEXTFIELD_TINY + " " + styleName)
|
||||||
|
.required(true).prompt(i18n.get(in18Key)).immediate(true).id(id).buildTextComponent();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void buildLayout() {
|
protected void buildLayout() {
|
||||||
|
|
||||||
|
|||||||
@@ -117,5 +117,4 @@ public class DSTypeFilterButtons extends AbstractFilterButtons {
|
|||||||
private void refreshTypeTable() {
|
private void refreshTypeTable() {
|
||||||
setContainerDataSource(createButtonsLazyQueryContainer());
|
setContainerDataSource(createButtonsLazyQueryContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
|||||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName;
|
import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName;
|
||||||
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent;
|
||||||
@@ -29,7 +28,6 @@ import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable;
|
|||||||
import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken;
|
import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken;
|
||||||
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
|
||||||
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder;
|
||||||
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
|
import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent;
|
||||||
import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleAssignmentDiscardEvent;
|
import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleAssignmentDiscardEvent;
|
||||||
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
|
import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState;
|
||||||
@@ -97,21 +95,6 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet
|
|||||||
|
|
||||||
private final Map<String, StringBuilder> assignedSWModule = new HashMap<>();
|
private final Map<String, StringBuilder> assignedSWModule = new HashMap<>();
|
||||||
|
|
||||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
|
||||||
void onEvent(final MetadataEvent event) {
|
|
||||||
UI.getCurrent().access(() -> {
|
|
||||||
final DistributionSetMetadata dsMetadata = event.getDistributionSetMetadata();
|
|
||||||
if (dsMetadata != null && isDistributionSetSelected(dsMetadata.getDistributionSet())) {
|
|
||||||
if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA) {
|
|
||||||
dsMetadataTable.createMetadata(event.getDistributionSetMetadata().getKey());
|
|
||||||
} else if (event
|
|
||||||
.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA) {
|
|
||||||
dsMetadataTable.deleteMetadata(event.getDistributionSetMetadata().getKey());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* softwareLayout Initialize the component.
|
* softwareLayout Initialize the component.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
|||||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||||
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionCreatedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionDeletedEvent;
|
||||||
|
import org.eclipse.hawkbit.repository.eventbus.event.DistributionSetUpdateEvent;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName;
|
import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName;
|
||||||
@@ -119,6 +122,33 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||||
|
void onEvents(final DistributionSetUpdateEvent event) {
|
||||||
|
final DistributionSet ds = event.getEntity();
|
||||||
|
final DistributionSetIdName lastSelectedDsIdName = manageDistUIState.getLastSelectedDistribution().isPresent()
|
||||||
|
? manageDistUIState.getLastSelectedDistribution().get() : null;
|
||||||
|
final List<DistributionSetIdName> visibleItemIds = (List<DistributionSetIdName>) getVisibleItemIds();
|
||||||
|
|
||||||
|
// refresh the details tabs only if selected ds is updated
|
||||||
|
if (lastSelectedDsIdName != null && lastSelectedDsIdName.getId().equals(ds.getId())) {
|
||||||
|
// update table row+details layout
|
||||||
|
eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, ds));
|
||||||
|
} else if (visibleItemIds.stream().filter(e -> e.getId().equals(ds.getId())).findFirst().isPresent()) {
|
||||||
|
// update the name/version details visible in table
|
||||||
|
UI.getCurrent().access(() -> updateDistributionInTable(event.getEntity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||||
|
void onEvents(final List<?> events) {
|
||||||
|
final Object firstEvent = events.get(0);
|
||||||
|
if (DistributionCreatedEvent.class.isInstance(firstEvent)) {
|
||||||
|
refreshDistributions();
|
||||||
|
} else if (DistributionDeletedEvent.class.isInstance(firstEvent)) {
|
||||||
|
onDistributionDeleteEvent((List<DistributionDeletedEvent>) events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTableId() {
|
protected String getTableId() {
|
||||||
return SPUIComponentIdProvider.DIST_TABLE_ID;
|
return SPUIComponentIdProvider.DIST_TABLE_ID;
|
||||||
@@ -414,6 +444,10 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
|||||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||||
void onEvent(final DistributionTableEvent event) {
|
void onEvent(final DistributionTableEvent event) {
|
||||||
onBaseEntityEvent(event);
|
onBaseEntityEvent(event);
|
||||||
|
if (BaseEntityEventType.UPDATED_ENTITY != event.getEventType()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UI.getCurrent().access(() -> updateDistributionInTable(event.getEntity()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventBusListenerMethod(scope = EventScope.SESSION)
|
@EventBusListenerMethod(scope = EventScope.SESSION)
|
||||||
@@ -459,6 +493,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
|||||||
@Override
|
@Override
|
||||||
protected void setDataAvailable(final boolean available) {
|
protected void setDataAvailable(final boolean available) {
|
||||||
manageDistUIState.setNoDataAvailableDist(!available);
|
manageDistUIState.setNoDataAvailableDist(!available);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -495,7 +530,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
|||||||
return manageMetadataBtn;
|
return manageMetadataBtn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMetadataDetails(final Long itemId) {
|
private void showMetadataDetails(final Long itemId) {
|
||||||
final DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(itemId);
|
final DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(itemId);
|
||||||
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null));
|
UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null));
|
||||||
}
|
}
|
||||||
@@ -507,4 +542,73 @@ public class DistributionSetTable extends AbstractNamedVersionTable<Distribution
|
|||||||
return name + "." + version;
|
return name + "." + version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void refreshDistributions() {
|
||||||
|
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||||
|
final int size = dsContainer.size();
|
||||||
|
if (size < SPUIDefinitions.MAX_TABLE_ENTRIES) {
|
||||||
|
refreshTablecontainer();
|
||||||
|
}
|
||||||
|
if (size != 0) {
|
||||||
|
setData(SPUIDefinitions.DATA_AVAILABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshTablecontainer() {
|
||||||
|
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||||
|
dsContainer.refresh();
|
||||||
|
selectRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDistributionInTable(final DistributionSet editedDs) {
|
||||||
|
final Item item = getContainerDataSource()
|
||||||
|
.getItem(new DistributionSetIdName(editedDs.getId(), editedDs.getName(), editedDs.getVersion()));
|
||||||
|
updateEntity(editedDs, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onDistributionDeleteEvent(final List<DistributionDeletedEvent> events) {
|
||||||
|
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||||
|
final List<Object> visibleItemIds = (List<Object>) getVisibleItemIds();
|
||||||
|
boolean shouldRefreshDs = false;
|
||||||
|
for (final DistributionDeletedEvent deletedEvent : events) {
|
||||||
|
final Long distributionSetId = deletedEvent.getDistributionSetId();
|
||||||
|
final DistributionSetIdName targetIdName = new DistributionSetIdName(distributionSetId, null, null);
|
||||||
|
if (visibleItemIds.contains(targetIdName)) {
|
||||||
|
dsContainer.removeItem(targetIdName);
|
||||||
|
} else {
|
||||||
|
shouldRefreshDs = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldRefreshDs) {
|
||||||
|
refreshOnDelete();
|
||||||
|
} else {
|
||||||
|
dsContainer.commit();
|
||||||
|
}
|
||||||
|
reSelectItemsAfterDeletionEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshOnDelete() {
|
||||||
|
final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource();
|
||||||
|
final int size = dsContainer.size();
|
||||||
|
refreshTablecontainer();
|
||||||
|
if (size != 0) {
|
||||||
|
setData(SPUIDefinitions.DATA_AVAILABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reSelectItemsAfterDeletionEvent() {
|
||||||
|
Set<Object> values = new HashSet<>();
|
||||||
|
if (isMultiSelect()) {
|
||||||
|
values = new HashSet<>((Set<?>) getValue());
|
||||||
|
} else {
|
||||||
|
values.add(getValue());
|
||||||
|
}
|
||||||
|
setValue(null);
|
||||||
|
|
||||||
|
for (final Object value : values) {
|
||||||
|
if (getVisibleItemIds().contains(value)) {
|
||||||
|
select(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ import org.eclipse.hawkbit.repository.SpPermissionChecker;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||||
import org.eclipse.hawkbit.ui.common.AbstractMetadataPopupLayout;
|
import org.eclipse.hawkbit.ui.common.AbstractMetadataPopupLayout;
|
||||||
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent;
|
|
||||||
import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent.MetadataUIEvent;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import com.vaadin.spring.annotation.SpringComponent;
|
import com.vaadin.spring.annotation.SpringComponent;
|
||||||
@@ -55,7 +53,6 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<Distribut
|
|||||||
final DistributionSetMetadata dsMetaData = distributionSetManagement
|
final DistributionSetMetadata dsMetaData = distributionSetManagement
|
||||||
.createDistributionSetMetadata(entityFactory.generateDistributionSetMetadata(entity, key, value));
|
.createDistributionSetMetadata(entityFactory.generateDistributionSetMetadata(entity, key, value));
|
||||||
setSelectedEntity(dsMetaData.getDistributionSet());
|
setSelectedEntity(dsMetaData.getDistributionSet());
|
||||||
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.CREATE_DISTRIBUTION_SET_METADATA, dsMetaData));
|
|
||||||
return dsMetaData;
|
return dsMetaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +81,6 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout<Distribut
|
|||||||
protected void deleteMetadata(final DistributionSet entity, final String key, final String value) {
|
protected void deleteMetadata(final DistributionSet entity, final String key, final String value) {
|
||||||
final DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value);
|
final DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value);
|
||||||
distributionSetManagement.deleteDistributionSetMetadata(entity, key);
|
distributionSetManagement.deleteDistributionSetMetadata(entity, key);
|
||||||
eventBus.publish(this, new MetadataEvent(MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA, dsMetaData));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import com.google.common.base.Strings;
|
|||||||
public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 5176481314404662215L;
|
private static final long serialVersionUID = 5176481314404662215L;
|
||||||
private Sort sort = new Sort(Direction.ASC, "name", "version");
|
private Sort sort = new Sort(Direction.ASC, "createdAt");
|
||||||
private String searchText = null;
|
private String searchText = null;
|
||||||
private transient DistributionSetManagement distributionSetManagement;
|
private transient DistributionSetManagement distributionSetManagement;
|
||||||
private transient Page<DistributionSet> firstPageDistributionSets = null;
|
private transient Page<DistributionSet> firstPageDistributionSets = null;
|
||||||
@@ -50,7 +50,7 @@ public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
|||||||
private DistributionSetType distributionSetType = null;
|
private DistributionSetType distributionSetType = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param definition
|
* @param definition
|
||||||
* @param queryConfig
|
* @param queryConfig
|
||||||
* @param sortPropertyIds
|
* @param sortPropertyIds
|
||||||
@@ -60,7 +60,7 @@ public class ManageDistBeanQuery extends AbstractBeanQuery<ProxyDistribution> {
|
|||||||
final Object[] sortPropertyIds, final boolean[] sortStates) {
|
final Object[] sortPropertyIds, final boolean[] sortStates) {
|
||||||
super(definition, queryConfig, sortPropertyIds, sortStates);
|
super(definition, queryConfig, sortPropertyIds, sortStates);
|
||||||
|
|
||||||
if (HawkbitCommonUtil.mapCheckStrKey(queryConfig)) {
|
if (HawkbitCommonUtil.isNotNullOrEmpty(queryConfig)) {
|
||||||
searchText = (String) queryConfig.get(SPUIDefinitions.FILTER_BY_TEXT);
|
searchText = (String) queryConfig.get(SPUIDefinitions.FILTER_BY_TEXT);
|
||||||
if (!Strings.isNullOrEmpty(searchText)) {
|
if (!Strings.isNullOrEmpty(searchText)) {
|
||||||
searchText = String.format("%%%s%%", searchText);
|
searchText = String.format("%%%s%%", searchText);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.ui.distributions.event;
|
|||||||
|
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Metadata Events.
|
* Metadata Events.
|
||||||
@@ -18,21 +19,21 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
|||||||
public class MetadataEvent {
|
public class MetadataEvent {
|
||||||
|
|
||||||
public enum MetadataUIEvent {
|
public enum MetadataUIEvent {
|
||||||
CREATE_DISTRIBUTION_SET_METADATA, DELETE_DISTRIBUTION_SET_METADATA, DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA;
|
DELETE_SOFTWARE_MODULE_METADATA, CREATE_SOFTWARE_MODULE_METADATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MetadataUIEvent metadataUIEvent;
|
private final MetadataUIEvent metadataUIEvent;
|
||||||
|
|
||||||
private DistributionSetMetadata distributionSetMetadata;
|
private DistributionSetMetadata distributionSetMetadata;
|
||||||
|
|
||||||
private SoftwareModuleMetadata softwareModuleMetadata;
|
private SoftwareModuleMetadata softwareModuleMetadata;
|
||||||
|
|
||||||
public MetadataEvent(MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) {
|
public MetadataEvent(final MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) {
|
||||||
this.metadataUIEvent = metadataUIEvent;
|
this.metadataUIEvent = metadataUIEvent;
|
||||||
this.distributionSetMetadata = distributionSetMetadata;
|
this.distributionSetMetadata = distributionSetMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetadataEvent(MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) {
|
public MetadataEvent(final MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) {
|
||||||
this.metadataUIEvent = metadataUIEvent;
|
this.metadataUIEvent = metadataUIEvent;
|
||||||
this.softwareModuleMetadata = softwareModuleMetadata;
|
this.softwareModuleMetadata = softwareModuleMetadata;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user