diff --git a/3rd-dependencies/listDeps.sh b/3rd-dependencies/listDeps.sh old mode 100644 new mode 100755 diff --git a/examples/hawkbit-device-simulator/README.md b/examples/hawkbit-device-simulator/README.md index 1ba29bb7e..0d73f3f3f 100644 --- a/examples/hawkbit-device-simulator/README.md +++ b/examples/hawkbit-device-simulator/README.md @@ -24,6 +24,12 @@ The simulator has user authentication enabled in **cloud profile**. Default cred 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 ### Graphical User Interface diff --git a/examples/hawkbit-device-simulator/cf/manifest.yml b/examples/hawkbit-device-simulator/cf/manifest.yml index 51a43ace6..188ef7780 100644 --- a/examples/hawkbit-device-simulator/cf/manifest.yml +++ b/examples/hawkbit-device-simulator/cf/manifest.yml @@ -17,6 +17,4 @@ applications: services: - dmf-rabbit env: - SPRING_PROFILES_ACTIVE: cloud,amqp - CF_STAGING_TIMEOUT: 15 - CF_STARTUP_TIMEOUT: 15 + SPRING_PROFILES_ACTIVE: cloud diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java index 69ed4fd4a..9c4c43ad2 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorUpdater.java @@ -118,6 +118,16 @@ public class DeviceSimulatorUpdater { } private static final class DeviceSimulatorUpdateThread implements Runnable { + /** + * + */ + private static final String BUT_GOT_LOG_MESSAGE = " but got: "; + + /** + * + */ + private static final String DOWNLOAD_LOG_MESSAGE = "Download "; + private static final int MINIMUM_TOKENLENGTH_FOR_HINT = 6; private static final Random rndSleep = new SecureRandom(); @@ -187,7 +197,7 @@ public class DeviceSimulatorUpdater { return result; } - private boolean isErrorResponse(final UpdateStatus status) { + private static boolean isErrorResponse(final UpdateStatus status) { if (status == null) { return false; } @@ -212,60 +222,73 @@ public class DeviceSimulatorUpdater { LOGGER.debug("Downloading {} with token {}, expected sha1 hash {} and size {}", url, hideTokenDetails(targetToken), sha1Hash, size); - long overallread = 0; try { - final CloseableHttpClient httpclient = createHttpClientThatAcceptsAllServerCerts(); - final HttpGet request = new HttpGet(url); - request.addHeader(HttpHeaders.AUTHORIZATION, "TargetToken " + targetToken); - - final String sha1HashResult; - try (final CloseableHttpResponse response = httpclient.execute(request)) { - - if (response.getStatusLine().getStatusCode() != HttpStatus.OK.value()) { - final String message = wrongStatusCode(url, response); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - - if (response.getEntity().getContentLength() != size) { - final String message = wrongContentLength(url, size, response); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - - // Exception squid:S2070 - not used for hashing sensitive - // data - @SuppressWarnings("squid:S2070") - final MessageDigest md = MessageDigest.getInstance("SHA-1"); - - try (final BufferedOutputStream bdos = new BufferedOutputStream( - new DigestOutputStream(ByteStreams.nullOutputStream(), md))) { - try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) { - overallread = ByteStreams.copy(bis, bdos); - } - } - - if (overallread != size) { - final String message = incompleteRead(url, size, overallread); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - - sha1HashResult = BaseEncoding.base16().lowerCase().encode(md.digest()); - } - - if (!sha1Hash.equalsIgnoreCase(sha1HashResult)) { - final String message = wrongHash(url, sha1Hash, overallread, sha1HashResult); - return new UpdateStatus(ResponseStatus.ERROR, message); - } - + return readAndCheckDownloadUrl(url, targetToken, sha1Hash, size); } catch (IOException | KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { LOGGER.error("Failed to download" + url, e); return new UpdateStatus(ResponseStatus.ERROR, "Failed to download " + url + ": " + e.getMessage()); } + } + + private static UpdateStatus readAndCheckDownloadUrl(final String url, final String targetToken, + final String sha1Hash, final long size) + throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException, IOException { + long overallread; + final CloseableHttpClient httpclient = createHttpClientThatAcceptsAllServerCerts(); + final HttpGet request = new HttpGet(url); + request.addHeader(HttpHeaders.AUTHORIZATION, "TargetToken " + targetToken); + + final String sha1HashResult; + try (final CloseableHttpResponse response = httpclient.execute(request)) { + + if (response.getStatusLine().getStatusCode() != HttpStatus.OK.value()) { + final String message = wrongStatusCode(url, response); + return new UpdateStatus(ResponseStatus.ERROR, message); + } + + if (response.getEntity().getContentLength() != size) { + final String message = wrongContentLength(url, size, response); + return new UpdateStatus(ResponseStatus.ERROR, message); + } + + // Exception squid:S2070 - not used for hashing sensitive + // data + @SuppressWarnings("squid:S2070") + final MessageDigest md = MessageDigest.getInstance("SHA-1"); + + overallread = getOverallRead(response, md); + + if (overallread != size) { + final String message = incompleteRead(url, size, overallread); + return new UpdateStatus(ResponseStatus.ERROR, message); + } + + sha1HashResult = BaseEncoding.base16().lowerCase().encode(md.digest()); + } + + if (!sha1Hash.equalsIgnoreCase(sha1HashResult)) { + final String message = wrongHash(url, sha1Hash, overallread, sha1HashResult); + return new UpdateStatus(ResponseStatus.ERROR, message); + } + final String message = "Downloaded " + url + " (" + overallread + " bytes)"; LOGGER.debug(message); return new UpdateStatus(ResponseStatus.SUCCESSFUL, message); } + private static long getOverallRead(final CloseableHttpResponse response, final MessageDigest md) + throws IOException { + long overallread; + try (final BufferedOutputStream bdos = new BufferedOutputStream( + new DigestOutputStream(ByteStreams.nullOutputStream(), md))) { + try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) { + overallread = ByteStreams.copy(bis, bdos); + } + } + return overallread; + } + private static String hideTokenDetails(final String targetToken) { if (targetToken == null) { return ""; @@ -285,29 +308,30 @@ public class DeviceSimulatorUpdater { private static String wrongHash(final String url, final String sha1Hash, final long overallread, final String sha1HashResult) { - final String message = "Download " + url + " failed with SHA1 hash missmatch (Expected: " + sha1Hash - + " but got: " + sha1HashResult + ") (" + overallread + " bytes)"; + final String message = DOWNLOAD_LOG_MESSAGE + url + " failed with SHA1 hash missmatch (Expected: " + + sha1Hash + BUT_GOT_LOG_MESSAGE + sha1HashResult + ") (" + overallread + " bytes)"; LOGGER.error(message); return message; } private static String incompleteRead(final String url, final long size, final long overallread) { - final String message = "Download " + url + " is incomplete (Expected: " + size + " but got: " + overallread - + ")"; + final String message = DOWNLOAD_LOG_MESSAGE + url + " is incomplete (Expected: " + size + + BUT_GOT_LOG_MESSAGE + overallread + ")"; LOGGER.error(message); return message; } private static String wrongContentLength(final String url, final long size, final CloseableHttpResponse response) { - final String message = "Download " + url + " has wrong content length (Expected: " + size + " but got: " - + response.getEntity().getContentLength() + ")"; + final String message = DOWNLOAD_LOG_MESSAGE + url + " has wrong content length (Expected: " + size + + BUT_GOT_LOG_MESSAGE + response.getEntity().getContentLength() + ")"; LOGGER.error(message); return message; } private static String wrongStatusCode(final String url, final CloseableHttpResponse response) { - final String message = "Download " + url + " failed (" + response.getStatusLine().getStatusCode() + ")"; + final String message = DOWNLOAD_LOG_MESSAGE + url + " failed (" + response.getStatusLine().getStatusCode() + + ")"; LOGGER.error(message); return message; } @@ -339,4 +363,5 @@ public class DeviceSimulatorUpdater { */ void updateFinished(AbstractSimulatedDevice device, final Long actionId); } + } diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatedDeviceFactory.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatedDeviceFactory.java index 8d5c5e0b1..3a8690cb3 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatedDeviceFactory.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatedDeviceFactory.java @@ -72,6 +72,7 @@ public class SimulatedDeviceFactory { final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) { switch (protocol) { case DMF_AMQP: + spSenderService.createOrUpdateThing(tenant, id); return new DMFSimulatedDevice(id, tenant, spSenderService, pollDelaySec); case DDI_HTTP: final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger()) diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java index 43f954c00..b100cb28f 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationController.java @@ -8,11 +8,13 @@ */ package org.eclipse.hawkbit.simulator; +import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX; + import java.net.MalformedURLException; import java.net.URL; 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.http.ResponseEntity; 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. - * - * - * */ @RestController public class SimulationController { - @Autowired - private SpSenderService spSenderService; - @Autowired private DeviceSimulatorRepository repository; @Autowired private SimulatedDeviceFactory deviceFactory; + @Autowired + private AmqpProperties amqpProperties; + /** * 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'"); } + 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++) { final String deviceId = name + i; 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!"); } + + private boolean isDmfDisabled() { + return !amqpProperties.isEnabled(); + } } diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java index 486eb4b5e..69ff765d0 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulatorStartup.java @@ -11,7 +11,7 @@ package org.eclipse.hawkbit.simulator; import java.net.MalformedURLException; 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.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -32,24 +32,27 @@ public class SimulatorStartup implements ApplicationListener { for (int i = 0; i < autostart.getAmount(); i++) { final String deviceId = autostart.getName() + i; try { - repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(), - autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()), - autostart.getGatewayToken())); + if (amqpProperties.isEnabled()) { + repository.add(deviceFactory.createSimulatedDevice(deviceId, autostart.getTenant(), + autostart.getApi(), autostart.getPollDelay(), new URL(autostart.getEndpoint()), + autostart.getGatewayToken())); + } + } catch (final MalformedURLException e) { LOGGER.error("Creation of simulated device at startup failed.", e); } diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java index edaf9d11a..5e9b3e049 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java @@ -8,6 +8,8 @@ */ package org.eclipse.hawkbit.simulator.amqp; +import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX; + import java.time.Duration; import java.util.HashMap; 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.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.amqp.RabbitProperties; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -39,6 +42,7 @@ import org.springframework.retry.support.RetryTemplate; */ @Configuration @EnableConfigurationProperties(AmqpProperties.class) +@ConditionalOnProperty(prefix = CONFIGURATION_PREFIX, name = "enabled") public class AmqpConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class); diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java index 8fba3ac5b..3730a3350 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java @@ -19,6 +19,17 @@ import org.springframework.stereotype.Component; @Component @ConfigurationProperties("hawkbit.device.simulator.amqp") 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. */ @@ -84,4 +95,12 @@ public class AmqpProperties { public void setDeadLetterTtl(final int deadLetterTtl) { this.deadLetterTtl = deadLetterTtl; } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(final boolean enabled) { + this.enabled = enabled; + } } diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java index f2c0e7fcb..d7f81be4e 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SenderService.java @@ -8,6 +8,7 @@ */ package org.eclipse.hawkbit.simulator.amqp; +import java.nio.charset.StandardCharsets; import java.util.UUID; import org.slf4j.Logger; @@ -58,7 +59,7 @@ public abstract class SenderService extends MessageService { } message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME); final String correlationId = UUID.randomUUID().toString(); - message.getMessageProperties().setCorrelationId(correlationId.getBytes()); + message.getMessageProperties().setCorrelationId(correlationId.getBytes(StandardCharsets.UTF_8)); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, address, correlationId); diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java index 4f2981be1..8dac6d4bc 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/SpReceiverService.java @@ -8,6 +8,8 @@ */ package org.eclipse.hawkbit.simulator.amqp; +import static org.eclipse.hawkbit.simulator.amqp.AmqpProperties.CONFIGURATION_PREFIX; + import java.util.Map; 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.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.messaging.handler.annotation.Header; import org.springframework.stereotype.Component; @@ -32,6 +35,7 @@ import com.google.common.collect.Lists; * */ @Component +@ConditionalOnProperty(prefix = CONFIGURATION_PREFIX, name = "enabled") public class SpReceiverService extends ReceiverService { private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class); @@ -67,8 +71,6 @@ public class SpReceiverService extends ReceiverService { * the incoming message * @param type * the action type - * @param contentType - * the content type in message header * @param thingId * the thing id in message header */ @@ -82,14 +84,11 @@ public class SpReceiverService extends ReceiverService { private void delegateMessage(final Message message, final String type, final String thingId) { final MessageType messageType = MessageType.valueOf(type); - switch (messageType) { - case EVENT: + if (MessageType.EVENT.equals(messageType)) { handleEventMessage(message, thingId); - break; - default: - LOGGER.info("No valid message type property."); - break; + return; } + LOGGER.info("No valid message type property."); } private void handleEventMessage(final Message message, final String thingId) { diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java index 272531407..6d1806463 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java @@ -33,9 +33,10 @@ import com.vaadin.ui.Window; * Popup dialog window for setting the values of generating the simulated * devices, e.g. the amount. * - * @author Michael Hirsch * */ +// Vaadin Inheritance +@SuppressWarnings("squid:MaximumInheritanceDepth") public class GenerateDialog extends Window { private static final long serialVersionUID = 1L; @@ -49,8 +50,9 @@ public class GenerateDialog extends Window { private final TextField pollDelayTextField; private final TextField pollUrlTextField; private final TextField gatewayTokenTextField; - private final OptionGroup protocolGroup; - private final Button buttonOk; + private OptionGroup protocolGroup; + private Button buttonOk; + private final boolean dmfEnabled; /** * Creates a new pop window for setting the configuration of simulating @@ -59,9 +61,12 @@ public class GenerateDialog extends Window { * @param callback * the callback which is called when the dialog has been * 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.setMargin(true); @@ -87,8 +92,8 @@ public class GenerateDialog extends Window { gatewayTokenTextField.setColumns(50); gatewayTokenTextField.setVisible(false); - protocolGroup = createProtocolGroup(); - buttonOk = createOkButton(callback); + createProtocolGroup(); + createOkButton(callback); namePrefixTextField.addValueChangeListener(event -> checkValid()); amountTextField.addValueChangeListener(event -> checkValid()); @@ -181,26 +186,29 @@ public class GenerateDialog extends Window { final URL basePollURL, final String gatewayToken, final Protocol protocol); } - private OptionGroup createProtocolGroup() { + private void createProtocolGroup() { - final OptionGroup protocolGroup = new OptionGroup("Simulated Device Protocol"); + this.protocolGroup = new OptionGroup("Simulated Device Protocol"); protocolGroup.addItem(Protocol.DMF_AMQP); protocolGroup.addItem(Protocol.DDI_HTTP); + protocolGroup.select(Protocol.DMF_AMQP); protocolGroup.setItemCaption(Protocol.DMF_AMQP, "Device Management Federation API (AMQP push)"); protocolGroup.setItemCaption(Protocol.DDI_HTTP, "Direct Device Interface (HTTP poll)"); protocolGroup.setNullSelectionAllowed(false); - protocolGroup.select(Protocol.DMF_AMQP); protocolGroup.addValueChangeListener(event -> { final boolean directDeviceOptionSelected = event.getProperty().getValue().equals(Protocol.DDI_HTTP); pollUrlTextField.setVisible(directDeviceOptionSelected); gatewayTokenTextField.setVisible(directDeviceOptionSelected); }); - return protocolGroup; + protocolGroup.setItemEnabled(Protocol.DMF_AMQP, dmfEnabled); + if (!dmfEnabled) { + protocolGroup.select(Protocol.DDI_HTTP); + } } - private Button createOkButton(final GenerateDialogCallback callback) { + private void createOkButton(final GenerateDialogCallback callback) { - final Button buttonOk = new Button("generate"); + this.buttonOk = new Button("generate"); buttonOk.setImmediate(true); buttonOk.setIcon(FontAwesome.GEARS); buttonOk.addClickListener(event -> { @@ -210,14 +218,11 @@ public class GenerateDialog extends Window { Integer.valueOf(pollDelayTextField.getValue().replace(".", "")), new URL(pollUrlTextField.getValue()), gatewayTokenTextField.getValue(), (Protocol) protocolGroup.getValue()); - } catch (final NumberFormatException e) { - LOGGER.info(e.getMessage(), e); - } catch (final MalformedURLException e) { + } catch (final NumberFormatException | MalformedURLException e) { LOGGER.info(e.getMessage(), e); } GenerateDialog.this.close(); }); - return buttonOk; } private TextField createRequiredTextfield(final String caption, final String value, final Resource icon, @@ -226,7 +231,7 @@ public class GenerateDialog extends Window { return addTextFieldValues(textField, icon, validator); } - private TextField createRequiredTextfield(final String caption, final Property dataSource, final Resource icon, + private TextField createRequiredTextfield(final String caption, final Property dataSource, final Resource icon, final Validator validator) { final TextField textField = new TextField(caption, dataSource); return addTextFieldValues(textField, icon, validator); diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorView.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorView.java index 9405edd2b..4a81547c5 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorView.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/ui/SimulatorView.java @@ -17,6 +17,7 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Status; import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository; import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory; import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus; +import org.eclipse.hawkbit.simulator.amqp.AmqpProperties; import org.eclipse.hawkbit.simulator.amqp.SpSenderService; import org.eclipse.hawkbit.simulator.event.InitUpdate; import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate; @@ -57,6 +58,11 @@ import com.vaadin.ui.renderers.ProgressBarRenderer; @SuppressWarnings("squid:MaximumInheritanceDepth") public class SimulatorView extends VerticalLayout implements View { + /** + * + */ + private static final String HTML_SPAN = ";"; + private static final String NEXT_POLL_COUNTER_SEC_COL = "nextPollCounterSec"; private static final String RESPONSE_STATUS_COL = "updateStatus"; @@ -85,6 +91,9 @@ public class SimulatorView extends VerticalLayout implements View { @Autowired private transient EventBus eventbus; + @Autowired + private transient AmqpProperties amqpProperties; + private final Label caption = new Label("DMF/DDI Simulated Devices"); private final HorizontalLayout toolbar = new HorizontalLayout(); private final Grid grid = new Grid(); @@ -261,94 +270,94 @@ public class SimulatorView extends VerticalLayout implements View { final String deviceId = namePrefix + index; beanContainer.addBean(repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant.toLowerCase(), protocol, pollDelay, basePollUrl, gatewayToken))); - spSenderService.createOrUpdateThing(tenant, deviceId); } - })); + }, amqpProperties.isEnabled())); } - private Converter createProtocolConverter() { - - return new Converter() { - - private static final long serialVersionUID = 1L; - - @Override - public Protocol convertToModel(final String value, final Class targetType, - final Locale locale) { - return null; - } - - @Override - public String convertToPresentation(final Protocol value, final Class targetType, - final Locale locale) { - switch (value) { - case DDI_HTTP: - return "DDI API (http)"; - case DMF_AMQP: - return "DMF API (amqp)"; - default: - return "unknown"; - } - } - - @Override - public Class getModelType() { - return Protocol.class; - } - - @Override - public Class getPresentationType() { - return String.class; - } - }; - + private ProtocolConverter createProtocolConverter() { + return new ProtocolConverter(); } - private Converter createStatusConverter() { - return new Converter() { - private static final long serialVersionUID = 1L; + private StatusConverter createStatusConverter() { + return new StatusConverter(); + } - @Override - public Status convertToModel(final String value, final Class targetType, - final Locale locale) { - return null; - } + public static final class ProtocolConverter implements Converter { + private static final long serialVersionUID = 1L; - @Override - public String convertToPresentation(final Status value, final Class targetType, - final Locale locale) { - switch (value) { - case UNKNWON: - return "&#x" - + Integer.toHexString(FontAwesome.QUESTION_CIRCLE.getCodepoint()) + ";"; - case PEDNING: - return "&#x" + Integer.toHexString(FontAwesome.REFRESH.getCodepoint()) - + ";"; - case FINISH: - return "&#x" - + Integer.toHexString(FontAwesome.CHECK_CIRCLE.getCodepoint()) + ";"; - case ERROR: - return "&#x" - + Integer.toHexString(FontAwesome.EXCLAMATION_CIRCLE.getCodepoint()) + ";"; - default: - throw new IllegalStateException("unknown value"); - } - } + @Override + public Protocol convertToModel(final String value, final Class targetType, + final Locale locale) { + return null; + } - @Override - public Class getModelType() { - return Status.class; + @Override + public String convertToPresentation(final Protocol value, final Class targetType, + final Locale locale) { + switch (value) { + case DDI_HTTP: + return "DDI API (http)"; + case DMF_AMQP: + return "DMF API (amqp)"; + default: + return "unknown"; } + } - @Override - public Class getPresentationType() { - return String.class; + @Override + public Class getModelType() { + return Protocol.class; + } + + @Override + public Class getPresentationType() { + return String.class; + } + } + + private static final class StatusConverter implements Converter { + private static final long serialVersionUID = 1L; + + @Override + public Status convertToModel(final String value, final Class targetType, + final Locale locale) { + return null; + } + + @Override + public String convertToPresentation(final Status value, final Class targetType, + final Locale locale) { + switch (value) { + case UNKNWON: + return "&#x" + Integer.toHexString(FontAwesome.QUESTION_CIRCLE.getCodepoint()) + + HTML_SPAN; + case PEDNING: + return "&#x" + Integer.toHexString(FontAwesome.REFRESH.getCodepoint()) + + HTML_SPAN; + case FINISH: + return "&#x" + Integer.toHexString(FontAwesome.CHECK_CIRCLE.getCodepoint()) + + HTML_SPAN; + case ERROR: + return "&#x" + + Integer.toHexString(FontAwesome.EXCLAMATION_CIRCLE.getCodepoint()) + HTML_SPAN; + default: + throw new IllegalStateException("unknown value"); } - }; + } + + @Override + public Class getModelType() { + return Status.class; + } + + @Override + public Class getPresentationType() { + return String.class; + } } } diff --git a/examples/hawkbit-device-simulator/src/main/resources/application.properties b/examples/hawkbit-device-simulator/src/main/resources/application.properties index 5d3f04be7..60fa817e2 100644 --- a/examples/hawkbit-device-simulator/src/main/resources/application.properties +++ b/examples/hawkbit-device-simulator/src/main/resources/application.properties @@ -8,6 +8,7 @@ # ## Configuration for DMF communication +hawkbit.device.simulator.amqp.enabled=true hawkbit.device.simulator.amqp.receiverConnectorQueueFromSp=simulator_receiver hawkbit.device.simulator.amqp.deadLetterQueue=simulator_deadletter hawkbit.device.simulator.amqp.deadLetterExchange=simulator.deadletter diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/amqp/AmqpAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/amqp/AmqpAutoConfiguration.java index 681e485fc..3e1f48c27 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/amqp/AmqpAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/amqp/AmqpAutoConfiguration.java @@ -10,8 +10,12 @@ package org.eclipse.hawkbit.autoconfigure.amqp; import org.eclipse.hawkbit.amqp.AmqpConfiguration; import org.eclipse.hawkbit.amqp.annotation.EnableAmqp; +import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.ErrorHandler; /** * The amqp autoconfiguration. @@ -24,4 +28,15 @@ import org.springframework.context.annotation.Configuration; @EnableAmqp public class AmqpAutoConfiguration { + /** + * Create default error handler bean. + * + * @return the default error handler bean + */ + @Bean + @ConditionalOnMissingBean + public ErrorHandler errorHandler() { + return new ConditionalRejectingErrorHandler(); + } + } diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/eventbus/EventBusAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/eventbus/EventBusAutoConfiguration.java index d4cc32825..c0cbabb08 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/eventbus/EventBusAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/eventbus/EventBusAutoConfiguration.java @@ -23,7 +23,7 @@ import com.google.common.eventbus.AsyncEventBus; import com.google.common.eventbus.EventBus; /** - * + * Auto configuration for the event bus. * */ @Configuration diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerAutoConfiguration.java index 7e2b780b4..eebfac6b0 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerAutoConfiguration.java @@ -21,7 +21,7 @@ import org.springframework.scheduling.annotation.EnableAsync; /** * - * + * Auto config fot the exception handler. */ @Configuration @EnableAsync diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java index a0d329ffa..9a7c7df52 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java @@ -70,6 +70,7 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; @@ -112,6 +113,8 @@ public class SecurityManagedConfiguration { */ @Bean @ConditionalOnMissingBean + // Exception squid:S00112 - Is aspectJ proxy + @SuppressWarnings({ "squid:S00112" }) public UserAuthenticationFilter userAuthenticationFilter() throws Exception { return new UserAuthenticationFilterBasicAuth(configuration.getAuthenticationManager()); } @@ -281,6 +284,9 @@ public class SecurityManagedConfiguration { @Autowired private SecurityProperties springSecurityProperties; + @Autowired + private SystemSecurityContext systemSecurityContext; + @Override protected void configure(final HttpSecurity http) throws Exception { @@ -309,14 +315,14 @@ public class SecurityManagedConfiguration { userAuthenticationFilter.destroy(); } }, RequestHeaderAuthenticationFilter.class) - .addFilterAfter( - new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement), - SessionManagementFilter.class) + .addFilterAfter(new AuthenticationSuccessTenantMetadataCreationFilter(systemManagement, + systemSecurityContext), SessionManagementFilter.class) .authorizeRequests().anyRequest().authenticated() .antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/admin/**") .hasAnyAuthority(SpPermission.SYSTEM_ADMIN); httpSec.httpBasic().and().exceptionHandling().authenticationEntryPoint(basicAuthEntryPoint); + httpSec.anonymous().disable(); } } @@ -465,12 +471,15 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends @Autowired private SystemManagement systemManagement; + @Autowired + private SystemSecurityContext systemSecurityContext; + @Override public void onAuthenticationSuccess(final Authentication authentication) throws Exception { if (authentication.getClass().equals(TenantUserPasswordAuthenticationToken.class)) { - systemManagement - .getTenantMetadata(((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString()); + systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(), + ((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString()); } else if (authentication.getClass().equals(UsernamePasswordAuthenticationToken.class)) { // TODO: vaadin4spring-ext-security does not give us the // fullyAuthenticatedToken @@ -479,7 +488,8 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends // LoginView. This needs to be changed with the update of // vaadin4spring 0.0.7 because it // has been fixed. - systemManagement.getTenantMetadata("DEFAULT"); + final String defaultTenant = "DEFAULT"; + systemSecurityContext.runAsSystemAsTenant(() -> systemManagement.getTenantMetadata(), defaultTenant); } super.onAuthenticationSuccess(authentication); @@ -491,13 +501,13 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends */ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { - private final TenantAware tenantAware; private final SystemManagement systemManagement; + private final SystemSecurityContext systemSecurityContext; - AuthenticationSuccessTenantMetadataCreationFilter(final TenantAware tenantAware, - final SystemManagement systemManagement) { - this.tenantAware = tenantAware; + AuthenticationSuccessTenantMetadataCreationFilter(final SystemManagement systemManagement, + final SystemSecurityContext systemSecurityContext) { this.systemManagement = systemManagement; + this.systemSecurityContext = systemSecurityContext; } @Override @@ -508,14 +518,16 @@ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter { @Override public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { - - final String currentTenant = tenantAware.getCurrentTenant(); - if (currentTenant != null) { - // lazy initialize tenant meta data after successful authentication - systemManagement.getTenantMetadata(currentTenant); - } - + lazyCreateTenantMetadata(); chain.doFilter(request, response); + + } + + private void lazyCreateTenantMetadata() { + final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication != null && authentication.isAuthenticated()) { + systemSecurityContext.runAsSystem(() -> systemManagement.getTenantMetadata()); + } } @Override diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java index fc3364d81..d9f759da3 100644 --- a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java +++ b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java @@ -56,6 +56,10 @@ public class RedisConfiguration { return new TenantAwareCacheManager(directCacheManager(), tenantAware); } + /** + * + * @return bean for the direct cache manager. + */ @Bean(name = "directCacheManager") public CacheManager directCacheManager() { return new RedisCacheManager(redisTemplate()); diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java index 8749340f0..973dcb6d6 100644 --- a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java +++ b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/eventbus/EventDistributor.java @@ -28,7 +28,7 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; /** - * + * The distributor for events. * */ @EventSubscriber @@ -100,11 +100,11 @@ public class EventDistributor { return topics; } - private void logDistributingEvent(final Event event, final String channel) { + private static void logDistributingEvent(final Event event, final String channel) { LOGGER.trace("distributing event {} from node {} to topic {}", event, NODE_ID, channel); } - private void logNotDistributingEvent(final Event event, final String channel) { + private static void logNotDistributingEvent(final Event event, final String channel) { LOGGER.debug("no redis template configured, event {} will not be distributed to channel {} from node {}", event, channel, NODE_ID); } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ArtifactUrlHandlerProperties.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ArtifactUrlHandlerProperties.java index c589e40e0..490b2d102 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ArtifactUrlHandlerProperties.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ArtifactUrlHandlerProperties.java @@ -16,9 +16,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; */ @ConfigurationProperties("hawkbit.artifact.url") public class ArtifactUrlHandlerProperties { - private static final String DEFAULT_IP_LOCALHOST = "127.0.0.1"; - private static final String DEFAULT_PORT = "8080"; - private static final String LOCALHOST = "localhost"; private final Http http = new Http(); private final Https https = new Https(); @@ -55,227 +52,45 @@ public class ArtifactUrlHandlerProperties { } } - /** - * Interface for declaring common properties through all supported protocols - * pattern. - */ - public interface ProtocolProperties { - /** - * @return the hostname value to resolve in the pattern. - */ - String getHostname(); - - /** - * @return the IP address value to resolve in the pattern. - */ - String getIp(); - - /** - * @return the port value to resolve in the pattern. - */ - String getPort(); - - /** - * @return the pattern to build the URL. - */ - String getPattern(); - - /** - * @return true if the {@link ProtocolProperties} is - * enabled. - */ - boolean isEnabled(); - } - /** * Object to hold the properties for the HTTP protocol. */ - public static class Http implements ProtocolProperties { - private String hostname = LOCALHOST; - private String ip = DEFAULT_IP_LOCALHOST; - private String port = DEFAULT_PORT; - /** - * An ant-URL pattern with placeholder to build the URL on. The URL can - * have specific artifact placeholder. - */ - private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"; + public static class Http extends DefaultProtocolProperties { /** - * Enables HTTP URI generation in DDI and DMF. + * Constructor. */ - private boolean enabled = true; - - @Override - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(final boolean enabled) { - this.enabled = enabled; - } - - @Override - public String getHostname() { - return hostname; - } - - public void setHostname(final String hostname) { - this.hostname = hostname; - } - - @Override - public String getIp() { - return ip; - } - - public void setIp(final String ip) { - this.ip = ip; - } - - @Override - public String getPattern() { - return pattern; - } - - public void setPattern(final String urlPattern) { - this.pattern = urlPattern; - } - - @Override - public String getPort() { - return port; - } - - public void setPort(final String port) { - this.port = port; + public Http() { + setPattern( + "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); } } /** * Object to hold the properties for the HTTP protocol. */ - public static class Https implements ProtocolProperties { - private String hostname = LOCALHOST; - private String ip = DEFAULT_IP_LOCALHOST; - private String port = DEFAULT_PORT; - /** - * An ant-URL pattern with placeholder to build the URL on. The URL can - * have specific artifact placeholder. - */ - private String pattern = "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"; + public static class Https extends DefaultProtocolProperties { /** - * Enables HTTPS URI generation in DDI and DMF. + * Constructor. */ - private boolean enabled = true; - - @Override - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(final boolean enabled) { - this.enabled = enabled; - } - - @Override - public String getHostname() { - return hostname; - } - - public void setHostname(final String hostname) { - this.hostname = hostname; - } - - @Override - public String getIp() { - return ip; - } - - public void setIp(final String ip) { - this.ip = ip; - } - - @Override - public String getPattern() { - return pattern; - } - - public void setPattern(final String urlPattern) { - this.pattern = urlPattern; - } - - @Override - public String getPort() { - return port; - } - - public void setPort(final String port) { - this.port = port; + public Https() { + setPattern( + "{protocol}://{hostname}:{port}/{tenant}/controller/v1/{targetId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}"); } } /** * Object to hold the properties for the HTTP protocol. */ - public static class Coap implements ProtocolProperties { - private String hostname = LOCALHOST; - private String ip = DEFAULT_IP_LOCALHOST; - private String port = "5683"; - /** - * An ant-URL pattern with placeholder to build the URL on. The URL can - * have specific artifact placeholder. - */ - private String pattern = "{protocol}://{ip}:{port}/fw/{tenant}/{targetId}/sha1/{artifactSHA1}"; + public static class Coap extends DefaultProtocolProperties { /** - * Enables CoAP URI generation in DMF. + * Constructor. */ - private boolean enabled = true; - - @Override - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(final boolean enabled) { - this.enabled = enabled; - } - - @Override - public String getHostname() { - return hostname; - } - - public void setHostname(final String hostname) { - this.hostname = hostname; - } - - @Override - public String getIp() { - return ip; - } - - public void setIp(final String ip) { - this.ip = ip; - } - - @Override - public String getPattern() { - return pattern; - } - - public void setPattern(final String urlPattern) { - this.pattern = urlPattern; - } - - @Override - public String getPort() { - return port; - } - - public void setPort(final String port) { - this.port = port; + public Coap() { + setPattern("{protocol}://{ip}:{port}/fw/{tenant}/{targetId}/sha1/{artifactSHA1}"); + setPort("5683"); } } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/DefaultProtocolProperties.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/DefaultProtocolProperties.java new file mode 100644 index 000000000..07eac8db1 --- /dev/null +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/DefaultProtocolProperties.java @@ -0,0 +1,79 @@ +/** + * 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.api; + +/** + * Object to hold the properties for the base protocols. + */ +public class DefaultProtocolProperties implements ProtocolProperties { + // The IP address is not hardcoded. It's the default value, if the IP + // address is not configured. + @SuppressWarnings("squid:S1313") + private static final String DEFAULT_IP_LOCALHOST = "127.0.0.1"; + private static final String LOCALHOST = "localhost"; + + private String hostname = LOCALHOST; + private String ip = DEFAULT_IP_LOCALHOST; + private String port = ""; + /** + * An ant-URL pattern with placeholder to build the URL on. The URL can have + * specific artifact placeholder. + */ + private String pattern; + + /** + * Enables protocol. + */ + private boolean enabled = true; + + @Override + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(final boolean enabled) { + this.enabled = enabled; + } + + @Override + public String getHostname() { + return hostname; + } + + public void setHostname(final String hostname) { + this.hostname = hostname; + } + + @Override + public String getIp() { + return ip; + } + + public void setIp(final String ip) { + this.ip = ip; + } + + @Override + public String getPattern() { + return pattern; + } + + public void setPattern(final String urlPattern) { + this.pattern = urlPattern; + } + + @Override + public String getPort() { + return port; + } + + public void setPort(final String port) { + this.port = port; + } +} diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java index d43d660ca..53f6492d1 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/PropertyBasedArtifactUrlHandler.java @@ -13,7 +13,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import org.eclipse.hawkbit.api.ArtifactUrlHandlerProperties.ProtocolProperties; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ProtocolProperties.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ProtocolProperties.java new file mode 100644 index 000000000..57f376c4e --- /dev/null +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ProtocolProperties.java @@ -0,0 +1,40 @@ +/** + * 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.api; + +/** + * Interface for declaring common properties through all supported protocols + * pattern. + */ +public interface ProtocolProperties { + /** + * @return the hostname value to resolve in the pattern. + */ + String getHostname(); + + /** + * @return the IP address value to resolve in the pattern. + */ + String getIp(); + + /** + * @return the port value to resolve in the pattern. + */ + String getPort(); + + /** + * @return the pattern to build the URL. + */ + String getPattern(); + + /** + * @return true if the {@link ProtocolProperties} is enabled. + */ + boolean isEnabled(); +} diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java index 5b58ea53e..9338bcbe7 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenancyCacheManager.java @@ -13,7 +13,7 @@ import org.springframework.cache.CacheManager; /** * - * + * A cache interface which handles multi tenancy. */ public interface TenancyCacheManager extends CacheManager { diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java index 435f1b2e1..055d9bf6c 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/TenantAwareCacheManager.java @@ -67,7 +67,7 @@ public class TenantAwareCacheManager implements TenancyCacheManager { public Collection getCacheNames() { String currentTenant = tenantAware.getCurrentTenant(); if (currentTenant == null) { - return null; + return Collections.emptyList(); } currentTenant = currentTenant.toUpperCase(); diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CancelTargetAssignmentEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CancelTargetAssignmentEvent.java index da93cc1a3..78c718f36 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CancelTargetAssignmentEvent.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/CancelTargetAssignmentEvent.java @@ -17,7 +17,7 @@ import java.net.URI; * * */ -public class CancelTargetAssignmentEvent extends AbstractEvent { +public class CancelTargetAssignmentEvent extends DefaultEvent { private final String controllerId; private final Long actionId; diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/DefaultEvent.java similarity index 87% rename from hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractEvent.java rename to hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/DefaultEvent.java index 498418169..1874fc01f 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/AbstractEvent.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/DefaultEvent.java @@ -12,11 +12,10 @@ package org.eclipse.hawkbit.eventbus.event; * Abstract event definition class which holds the necessary revsion and tenant * information which every event needs. * - * @author Michael Hirsch * @see AbstractDistributedEvent for events which should be distributed to other * cluster nodes */ -public class AbstractEvent implements Event { +public class DefaultEvent implements Event { private final long revision; private final String tenant; @@ -27,7 +26,7 @@ public class AbstractEvent implements Event { * @param tenant * the tenant of the event */ - protected AbstractEvent(final long revision, final String tenant) { + protected DefaultEvent(final long revision, final String tenant) { this.revision = revision; this.tenant = tenant; } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetDeletedEvent.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetDeletedEvent.java index e6fcac135..048274abc 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetDeletedEvent.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/eventbus/event/TargetDeletedEvent.java @@ -9,9 +9,7 @@ package org.eclipse.hawkbit.eventbus.event; /** - * - * - * + * The event when a target is deleted. */ public class TargetDeletedEvent extends AbstractDistributedEvent { diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerRtException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/AbstractServerRtException.java similarity index 79% rename from hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerRtException.java rename to hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/AbstractServerRtException.java index ba691bb5f..cb695d2f7 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerRtException.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/AbstractServerRtException.java @@ -15,8 +15,7 @@ package org.eclipse.hawkbit.exception; * Generic Custom Exception to wrap the Runtime and checked exception * */ - -public abstract class SpServerRtException extends RuntimeException { +public abstract class AbstractServerRtException extends RuntimeException { private static final long serialVersionUID = 1L; @@ -28,7 +27,7 @@ public abstract class SpServerRtException extends RuntimeException { * @param error * detail */ - public SpServerRtException(final SpServerError error) { + public AbstractServerRtException(final SpServerError error) { super(error.getMessage()); this.error = error; } @@ -41,7 +40,7 @@ public abstract class SpServerRtException extends RuntimeException { * @param error * detail */ - public SpServerRtException(final String message, final SpServerError error) { + public AbstractServerRtException(final String message, final SpServerError error) { super(message); this.error = error; } @@ -56,7 +55,7 @@ public abstract class SpServerRtException extends RuntimeException { * @param cause * of the exception */ - public SpServerRtException(final String message, final SpServerError error, final Throwable cause) { + public AbstractServerRtException(final String message, final SpServerError error, final Throwable cause) { super(message, cause); this.error = error; } @@ -69,7 +68,7 @@ public abstract class SpServerRtException extends RuntimeException { * @param cause * of the exception */ - public SpServerRtException(final SpServerError error, final Throwable cause) { + public AbstractServerRtException(final SpServerError error, final Throwable cause) { super(error.getMessage(), cause); this.error = error; } diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java index f0a3f4d1f..4ac02e081 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/GenericSpServerException.java @@ -16,7 +16,7 @@ package org.eclipse.hawkbit.exception; * * */ -public class GenericSpServerException extends SpServerRtException { +public class GenericSpServerException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_GENERIC_ERROR; diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java index c2d8ec49d..237fed978 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionFields.java @@ -11,11 +11,8 @@ package org.eclipse.hawkbit.repository; /** * Sort fields for {@link ActionRest}. * - * - * - * */ -public enum ActionFields implements FieldNameProvider,FieldValueConverter { +public enum ActionFields implements FieldNameProvider, FieldValueConverter { /** * The status field. @@ -42,13 +39,10 @@ public enum ActionFields implements FieldNameProvider,FieldValueConverter contains contains not + */ default boolean containsSubEntityAttribute(final String propertyField) { return FieldNameProvider.containsSubEntityAttribute(propertyField, getSubEntityAttributes()); - }; + } + /** + * + * @return all sub entities attributes. + */ default List getSubEntityAttributes() { return Collections.emptyList(); - }; + } /** * the database column for the key @@ -59,11 +70,11 @@ public interface FieldNameProvider { /** * Is the entity field a {@link Map}. * - * @return + * @return is a map is not a map */ default boolean isMap() { return getKeyFieldName() != null; - }; + } /** * Check if a sub attribute exists. diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/DurationHelper.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/DurationHelper.java index 5968f4420..befd00c5d 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/DurationHelper.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/DurationHelper.java @@ -27,7 +27,7 @@ public final class DurationHelper { * the defined min/max range. * */ - public static class DurationRangeValidator { + public static final class DurationRangeValidator { final Duration min; final Duration max; diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/InvalidTenantConfigurationKeyException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/InvalidTenantConfigurationKeyException.java index dcc42065c..977b66a6a 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/InvalidTenantConfigurationKeyException.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/InvalidTenantConfigurationKeyException.java @@ -9,14 +9,14 @@ package org.eclipse.hawkbit.tenancy.configuration; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * The {@link #InvalidTenantConfigurationKeyException} is thrown when an invalid * configuration key is used. * */ -public class InvalidTenantConfigurationKeyException extends SpServerRtException { +public class InvalidTenantConfigurationKeyException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_CONFIGURATION_KEY_INVALID; diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidator.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidator.java index dccf515e6..bb61f1ec5 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidator.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidator.java @@ -22,7 +22,7 @@ public interface TenantConfigurationValidator { * @throws TenantConfigurationValidatorException * is thrown, when parameter is invalid. */ - default void validate(final Object tenantConfigurationValue) throws TenantConfigurationValidatorException { + default void validate(final Object tenantConfigurationValue) { if (tenantConfigurationValue != null && validateToClass().isAssignableFrom(tenantConfigurationValue.getClass())) { return; diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidatorException.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidatorException.java index dffc13dcb..4cc545287 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidatorException.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/validator/TenantConfigurationValidatorException.java @@ -9,14 +9,14 @@ package org.eclipse.hawkbit.tenancy.configuration.validator; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception which is thrown, when the validation of the configuration value has * not been successful. * */ -public class TenantConfigurationValidatorException extends SpServerRtException { +public class TenantConfigurationValidatorException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_CONFIGURATION_VALUE_INVALID; diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java index 9541055f8..898ee244a 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiArtifactHash.java @@ -27,6 +27,7 @@ public class DdiArtifactHash { * Default constructor. */ public DdiArtifactHash() { + // needed for json create } /** diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java index 78de8591d..cf146b597 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiChunk.java @@ -29,7 +29,7 @@ public class DdiChunk { private List artifacts; public DdiChunk() { - + // needed for json create } /** diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java index 5ec1b4dde..0dfed6e79 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiConfig.java @@ -34,8 +34,11 @@ public class DdiConfig { this.polling = polling; } + /** + * Constructor. + */ public DdiConfig() { - + // needed for json create. } public DdiPolling getPolling() { diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java index 3f160157c..526227601 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiControllerBase.java @@ -37,7 +37,7 @@ public class DdiControllerBase extends ResourceSupport { } public DdiControllerBase() { - + // needed for json create } public DdiConfig getConfig() { diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java index f72083d7a..c7e364b36 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeployment.java @@ -23,8 +23,11 @@ public class DdiDeployment { private List chunks; + /** + * Constructor. + */ public DdiDeployment() { - + // needed for json create. } /** diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java index 8f1116b1b..a8f5ee72b 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiDeploymentBase.java @@ -12,6 +12,7 @@ import javax.validation.constraints.NotNull; import org.springframework.hateoas.ResourceSupport; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; /** @@ -21,10 +22,10 @@ public class DdiDeploymentBase extends ResourceSupport { @JsonProperty("id") @NotNull - private String deplyomentId; + private final String deplyomentId; @NotNull - private DdiDeployment deployment; + private final DdiDeployment deployment; /** * Constructor. @@ -34,15 +35,13 @@ public class DdiDeploymentBase extends ResourceSupport { * @param deployment * details. */ - public DdiDeploymentBase(final String id, final DdiDeployment deployment) { - deplyomentId = id; + @JsonCreator + public DdiDeploymentBase(@JsonProperty("id") final String id, + @JsonProperty("deplyomentId") final DdiDeployment deployment) { + this.deplyomentId = id; this.deployment = deployment; } - public DdiDeploymentBase() { - - } - public DdiDeployment getDeployment() { return deployment; } diff --git a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java index 489178be8..81427510a 100644 --- a/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java +++ b/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiPolling.java @@ -30,11 +30,15 @@ public class DdiPolling { * between polls */ public DdiPolling(final String sleep) { - super(); this.sleep = sleep; } + /** + * Constructor. + * + */ public DdiPolling() { + // needed for json create } public String getSleep() { diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java index 0ec0d0d7e..584c774d5 100644 --- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java +++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiDeploymentBaseTest.java @@ -60,8 +60,8 @@ import ru.yandex.qatools.allure.annotations.Stories; @Stories("Deployment Action Resource") public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoDB { - private static final String HTTP_LOCALHOST = "http://localhost:8080/"; - private static final String HTTPS_LOCALHOST = "https://localhost:8080/"; + private static final String HTTP_LOCALHOST = "http://localhost/"; + private static final String HTTPS_LOCALHOST = "https://localhost/"; @Test() @Description("Ensures that artifacts are not found, when softare module does not exists.") diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java index 31ec37c58..ba5e3d2f6 100644 --- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java +++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootControllerTest.java @@ -8,6 +8,10 @@ */ package org.eclipse.hawkbit.ddi.rest.resource; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE; import static org.fest.assertions.api.Assertions.assertThat; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.Matchers.startsWith; @@ -23,7 +27,6 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.hawkbit.im.authentication.SpPermission; -import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; @@ -57,7 +60,8 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD @Test @Description("Ensures that targets cannot be created e.g. in plug'n play scenarios when tenant does not exists but can be created if the tenant exists.") - @WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = "ROLE_CONTROLLER", autoCreateTenant = false) + @WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = { CONTROLLER_ROLE, + SYSTEM_ROLE }, autoCreateTenant = false) public void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception { mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print()) @@ -91,13 +95,11 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD // make a poll, audit information should not be changed, run as // controller principal! - securityRule.runAs( - WithSpringAuthorityRule.withUser("controller", SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS), () -> { - mvc.perform( - get("/{tenant}/controller/v1/" + knownTargetControllerId, tenantAware.getCurrentTenant())) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); - return null; - }); + securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + mvc.perform(get("/{tenant}/controller/v1/" + knownTargetControllerId, tenantAware.getCurrentTenant())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); + return null; + }); // verify that audit information has not changed final Target targetVerify = targetManagement.findTargetByControllerID(knownTargetControllerId); @@ -143,22 +145,19 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD @Description("Ensures that tenant specific polling time, which is saved in the db, is delivered to the controller.") @WithUser(principal = "knownpricipal", allSpPermissions = false) public void pollWithModifiedGloablPollingTime() throws Exception { - securityRule.runAs( - WithSpringAuthorityRule.withUser("tenantadmin", SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION), - () -> { - tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, - "00:02:00"); - return null; - }); + securityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> { + tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, + "00:02:00"); + return null; + }); - securityRule.runAs( - WithSpringAuthorityRule.withUser("controller", SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS), () -> { - mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())) - .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) - .andExpect(content().contentType(MediaTypes.HAL_JSON)) - .andExpect(jsonPath("$config.polling.sleep", equalTo("00:02:00"))); - return null; - }); + securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { + mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())) + .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) + .andExpect(content().contentType(MediaTypes.HAL_JSON)) + .andExpect(jsonPath("$config.polling.sleep", equalTo("00:02:00"))); + return null; + }); } @Test diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java index 11f892654..bcac6a6e5 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java @@ -37,7 +37,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.retry.backoff.ExponentialBackOffPolicy; -import org.springframework.retry.support.RetryTemplate;; +import org.springframework.retry.support.RetryTemplate; +import org.springframework.util.ErrorHandler; /** * The spring AMQP configuration which is enabled by using the profile @@ -263,13 +264,16 @@ public class AmqpConfiguration { /** * Returns the Listener factory. - * + * + * @param errorHandler + * the error hander * @return the {@link SimpleMessageListenerContainer} that gets used receive * AMQP messages */ @Bean(name = { "listenerContainerFactory" }) - public RabbitListenerContainerFactory listenerContainerFactory() { - return new ConfigurableRabbitListenerContainerFactory(amqpProperties, rabbitConnectionFactory); + public RabbitListenerContainerFactory listenerContainerFactory( + final ErrorHandler errorHandler) { + return new ConfigurableRabbitListenerContainerFactory(amqpProperties, rabbitConnectionFactory, errorHandler); } private static Map getTTLMaxArgsAuthenticationQueue() { diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java index 91d07de37..788d1d8d8 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java @@ -36,7 +36,7 @@ import org.springframework.stereotype.Component; /** * - * + * A controller which handles the amqp authentfication. */ @Component public class AmqpControllerAuthentfication { diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java index d1bf85103..8906bc96c 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.amqp; import java.net.URI; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; import java.util.UUID; @@ -137,6 +138,13 @@ public class AmqpMessageHandlerService extends BaseAmqpService { return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost()); } + /** + * Executed on a authentication request. + * + * @param message + * the amqp message + * @return the rpc message back to supplier. + */ @RabbitListener(queues = "${hawkbit.dmf.rabbitmq.authenticationReceiverQueue}", containerFactory = "listenerContainerFactory") public Message onAuthenticationRequest(final Message message) { checkContentTypeJson(message); @@ -152,6 +160,19 @@ public class AmqpMessageHandlerService extends BaseAmqpService { } } + /** + * * Executed if a amqp message arrives. + * + * @param message + * the message + * @param type + * the type + * @param tenant + * the tenant + * @param virtualHost + * the virtual host + * @return the rpc message back to supplier. + */ public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) { checkContentTypeJson(message); final SecurityContext oldContext = SecurityContextHolder.getContext(); @@ -417,7 +438,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService { } private static String convertCorrelationId(final Message message) { - return new String(message.getMessageProperties().getCorrelationId()); + return new String(message.getMessageProperties().getCorrelationId(), StandardCharsets.UTF_8); } private Action getUpdateActionStatus(final ActionStatus actionStatus) { diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/BaseAmqpService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/BaseAmqpService.java index 88c88f264..b11d5a437 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/BaseAmqpService.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/BaseAmqpService.java @@ -39,16 +39,6 @@ public class BaseAmqpService { this.rabbitTemplate = rabbitTemplate; } - /** - * Clean message properties before sending a message. - * - * @param message - * the message to cleaned up - */ - protected void cleanMessageHeaderProperties(final Message message) { - message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME); - } - /** * Is needed to convert a incoming message to is originally object type. * @@ -68,7 +58,7 @@ public class BaseAmqpService { return (T) rabbitTemplate.getMessageConverter().fromMessage(message); } - private boolean isMessageBodyEmpty(final Message message) { + private static boolean isMessageBodyEmpty(final Message message) { return message == null || message.getBody() == null || message.getBody().length == 0; } @@ -98,8 +88,7 @@ public class BaseAmqpService { return rabbitTemplate.getMessageConverter(); } - protected final String getStringHeaderKey(final Message message, final String key, - final String errorMessageIfNull) { + protected String getStringHeaderKey(final Message message, final String key, final String errorMessageIfNull) { final Map header = message.getMessageProperties().getHeaders(); final Object value = header.get(key); if (value == null) { @@ -117,4 +106,15 @@ public class BaseAmqpService { protected RabbitTemplate getRabbitTemplate() { return rabbitTemplate; } + + /** + * Clean message properties before sending a message. + * + * @param message + * the message to cleaned up + */ + protected void cleanMessageHeaderProperties(final Message message) { + message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME); + } + } diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/ConfigurableRabbitListenerContainerFactory.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/ConfigurableRabbitListenerContainerFactory.java index 14e6f8fcb..b213e744b 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/ConfigurableRabbitListenerContainerFactory.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/ConfigurableRabbitListenerContainerFactory.java @@ -12,6 +12,7 @@ import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFacto import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory; import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; +import org.springframework.util.ErrorHandler; /** * {@link RabbitListenerContainerFactory} that can be configured through @@ -28,10 +29,13 @@ public class ConfigurableRabbitListenerContainerFactory extends SimpleRabbitList * for the container factory * @param amqpProperties * to configure the container factory + * @param errorHandler + * the error handler which should be use */ public ConfigurableRabbitListenerContainerFactory(final AmqpProperties amqpProperties, - final ConnectionFactory rabbitConnectionFactory) { + final ConnectionFactory rabbitConnectionFactory, final ErrorHandler errorHandler) { this.amqpProperties = amqpProperties; + setErrorHandler(errorHandler); setDefaultRequeueRejected(true); setConnectionFactory(rabbitConnectionFactory); setMissingQueuesFatal(amqpProperties.isMissingQueuesFatal()); diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DefaultAmqpSenderService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DefaultAmqpSenderService.java index d951cce5d..1eb6d31f2 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DefaultAmqpSenderService.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/DefaultAmqpSenderService.java @@ -9,6 +9,7 @@ package org.eclipse.hawkbit.amqp; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.util.UUID; import org.eclipse.hawkbit.util.IpUtil; @@ -46,7 +47,7 @@ public class DefaultAmqpSenderService implements AmqpSenderService { final String correlationId = UUID.randomUUID().toString(); final String exchange = extractExchange(replyTo); - message.getMessageProperties().setCorrelationId(correlationId.getBytes()); + message.getMessageProperties().setCorrelationId(correlationId.getBytes(StandardCharsets.UTF_8)); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, exchange, correlationId); diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java index 4e08e1852..211ac26a2 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java @@ -114,7 +114,7 @@ public class AmqpControllerAuthenticationTest { @Description("Tests authentication manager without principal") public void testAuthenticationeBadCredantialsWithoutPricipal() { final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, - FileResource.sha1("12345")); + FileResource.createFileResourceBySha1("12345")); try { authenticationManager.doAuthenticate(securityToken); fail("BadCredentialsException was excepeted since principal was missing"); @@ -128,7 +128,7 @@ public class AmqpControllerAuthenticationTest { @Description("Tests authentication manager without wrong credential") public void testAuthenticationBadCredantialsWithWrongCredential() { final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, - FileResource.sha1("12345")); + FileResource.createFileResourceBySha1("12345")); when(tenantConfigurationManagement.getConfigurationValue( eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) .thenReturn(CONFIG_VALUE_TRUE); @@ -146,7 +146,7 @@ public class AmqpControllerAuthenticationTest { @Description("Tests authentication successfull") public void testSuccessfullAuthentication() { final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, - FileResource.sha1("12345")); + FileResource.createFileResourceBySha1("12345")); when(tenantConfigurationManagement.getConfigurationValue( eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) .thenReturn(CONFIG_VALUE_TRUE); @@ -161,7 +161,7 @@ public class AmqpControllerAuthenticationTest { final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, - FileResource.sha1("12345")); + FileResource.createFileResourceBySha1("12345")); final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, messageProperties); @@ -179,7 +179,7 @@ public class AmqpControllerAuthenticationTest { public void testAuthenticationMessageBadCredantialsWithWrongCredential() { final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, - FileResource.sha1("12345")); + FileResource.createFileResourceBySha1("12345")); when(tenantConfigurationManagement.getConfigurationValue( eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) .thenReturn(CONFIG_VALUE_TRUE); @@ -201,7 +201,7 @@ public class AmqpControllerAuthenticationTest { public void testSuccessfullMessageAuthentication() { final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, - FileResource.sha1("12345")); + FileResource.createFileResourceBySha1("12345")); when(tenantConfigurationManagement.getConfigurationValue( eq(TenantConfigurationKey.AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED), eq(Boolean.class))) .thenReturn(CONFIG_VALUE_TRUE); diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java index 2627731c6..7a3915e28 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java @@ -279,7 +279,8 @@ public class AmqpMessageHandlerServiceTest { @Description("Tests that an download request is denied for an artifact which does not exists") public void authenticationRequestDeniedForArtifactWhichDoesNotExists() { final MessageProperties messageProperties = createMessageProperties(null); - final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); + final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", + FileResource.createFileResourceBySha1("12345")); final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, messageProperties); @@ -297,7 +298,8 @@ public class AmqpMessageHandlerServiceTest { @Description("Tests that an download request is denied for an artifact which is not assigned to the requested target") public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() { final MessageProperties messageProperties = createMessageProperties(null); - final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); + final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", + FileResource.createFileResourceBySha1("12345")); final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, messageProperties); @@ -320,7 +322,8 @@ public class AmqpMessageHandlerServiceTest { @Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target") public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException { final MessageProperties messageProperties = createMessageProperties(null); - final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); + final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", + FileResource.createFileResourceBySha1("12345")); final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, messageProperties); diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java index 8cd92d2bd..92e8f390d 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java @@ -35,8 +35,8 @@ import ru.yandex.qatools.allure.annotations.Stories; org.eclipse.hawkbit.RepositoryApplicationConfiguration.class }) public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB { - private static final String HTTPS_LOCALHOST = "https://localhost:8080/"; - private static final String HTTP_LOCALHOST = "http://localhost:8080/"; + private static final String HTTPS_LOCALHOST = "https://localhost/"; + private static final String HTTP_LOCALHOST = "http://localhost/"; @Autowired private ArtifactUrlHandler urlHandlerProperties; diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java index e4f41bc46..19293f3eb 100644 --- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java +++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/TenantSecurityToken.java @@ -135,7 +135,7 @@ public class TenantSecurityToken { * the SHA1 key of the file to obtain * @return the {@link FileResource} with SHA1 key set */ - public static FileResource sha1(final String sha1) { + public static FileResource createFileResourceBySha1(final String sha1) { final FileResource resource = new FileResource(); resource.sha1 = sha1; return resource; @@ -148,7 +148,7 @@ public class TenantSecurityToken { * the filename of the file to obtain * @return the {@link FileResource} with filename set */ - public static FileResource filename(final String filename) { + public static FileResource createFileResourceByFilename(final String filename) { final FileResource resource = new FileResource(); resource.filename = filename; return resource; diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java index 48e54eca1..9aa5c72f9 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/AbstractHttpControllerAuthenticationFilter.java @@ -47,7 +47,7 @@ import com.google.common.collect.UnmodifiableIterator; */ public abstract class AbstractHttpControllerAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractHttpControllerAuthenticationFilter.class); + private static final Logger LOG = LoggerFactory.getLogger(AbstractHttpControllerAuthenticationFilter.class); private static final String TENANT_PLACE_HOLDER = "tenant"; private static final String CONTROLLER_ID_PLACE_HOLDER = "controllerId"; @@ -73,10 +73,12 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac /** * Constructor for sub-classes. * - * @param systemManagement - * the system management service + * @param tenantConfigurationManagement + * the tenant configuration service * @param tenantAware * the tenant aware service + * @param systemSecurityContext + * the system secruity context */ public AbstractHttpControllerAuthenticationFilter(final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware, final SystemSecurityContext systemSecurityContext) { @@ -136,28 +138,28 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac final String requestURI = request.getRequestURI(); if (pathExtractor.match(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI)) { - LOGGER.debug("retrieving principal from URI request {}", requestURI); + LOG.debug("retrieving principal from URI request {}", requestURI); final Map extractUriTemplateVariables = pathExtractor .extractUriTemplateVariables(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI); final String controllerId = extractUriTemplateVariables.get(CONTROLLER_ID_PLACE_HOLDER); final String tenant = extractUriTemplateVariables.get(TENANT_PLACE_HOLDER); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Parsed tenant {} and controllerId {} from path request {}", tenant, controllerId, + if (LOG.isTraceEnabled()) { + LOG.trace("Parsed tenant {} and controllerId {} from path request {}", tenant, controllerId, requestURI); } return createTenantSecruityTokenVariables(request, tenant, controllerId); } else if (pathExtractor.match(request.getContextPath() + CONTROLLER_DL_REQUEST_ANT_PATTERN, requestURI)) { - LOGGER.debug("retrieving path variables from URI request {}", requestURI); + LOG.debug("retrieving path variables from URI request {}", requestURI); final Map extractUriTemplateVariables = pathExtractor.extractUriTemplateVariables( request.getContextPath() + CONTROLLER_DL_REQUEST_ANT_PATTERN, requestURI); final String tenant = extractUriTemplateVariables.get(TENANT_PLACE_HOLDER); - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Parsed tenant {} from path request {}", tenant, requestURI); + if (LOG.isTraceEnabled()) { + LOG.trace("Parsed tenant {} from path request {}", tenant, requestURI); } return createTenantSecruityTokenVariables(request, tenant, "anonymous"); } else { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("request {} does not match the path pattern {}, request gets ignored", requestURI, + if (LOG.isTraceEnabled()) { + LOG.trace("request {} does not match the path pattern {}, request gets ignored", requestURI, CONTROLLER_REQUEST_ANT_PATTERN); } return null; @@ -166,7 +168,8 @@ public abstract class AbstractHttpControllerAuthenticationFilter extends Abstrac private TenantSecurityToken createTenantSecruityTokenVariables(final HttpServletRequest request, final String tenant, final String controllerId) { - final TenantSecurityToken secruityToken = new TenantSecurityToken(tenant, controllerId, FileResource.sha1("")); + final TenantSecurityToken secruityToken = new TenantSecurityToken(tenant, controllerId, + FileResource.createFileResourceBySha1("")); final UnmodifiableIterator forEnumeration = Iterators.forEnumeration(request.getHeaderNames()); forEnumeration.forEachRemaining(header -> secruityToken.getHeaders().put(header, request.getHeader(header))); return secruityToken; diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/ControllerTenantAwareAuthenticationDetailsSource.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/ControllerTenantAwareAuthenticationDetailsSource.java index 80d50112f..ae514c07b 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/ControllerTenantAwareAuthenticationDetailsSource.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/ControllerTenantAwareAuthenticationDetailsSource.java @@ -22,15 +22,11 @@ import org.springframework.util.AntPathMatcher; * An {@link AuthenticationDetailsSource} implementation which retrieves the * tenant from a request pattern {@link #TENANT_AWARE_CONTROLLER_PATTERN} and * stores the retrieved tenant in the {@link TenantAwareAuthenticationDetails}. - * * */ public class ControllerTenantAwareAuthenticationDetailsSource implements AuthenticationDetailsSource { - /** - * - */ private static final String TENANT_AWARE_CONTROLLER_PATTERN = "/{tenant}/controller/**"; private static final Logger LOGGER = LoggerFactory .getLogger(ControllerTenantAwareAuthenticationDetailsSource.class); @@ -38,19 +34,12 @@ public class ControllerTenantAwareAuthenticationDetailsSource private final AntPathMatcher pathExtractor; /** - * - */ + * Constructor. + */ public ControllerTenantAwareAuthenticationDetailsSource() { pathExtractor = new AntPathMatcher(); } - /* - * (non-Javadoc) - * - * @see - * org.springframework.security.authentication.AuthenticationDetailsSource# - * buildDetails(java. lang.Object) - */ @Override public TenantAwareAuthenticationDetails buildDetails(final HttpServletRequest request) { return new TenantAwareWebAuthenticationDetails(getTenantFromRequestUri(request), request.getRemoteAddr(), true); diff --git a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpDownloadAuthenticationFilter.java b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpDownloadAuthenticationFilter.java index 4a4bf2f5c..4185c9b83 100644 --- a/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpDownloadAuthenticationFilter.java +++ b/hawkbit-http-security/src/main/java/org/eclipse/hawkbit/security/HttpDownloadAuthenticationFilter.java @@ -28,7 +28,7 @@ import org.springframework.security.web.authentication.preauth.AbstractPreAuthen public class HttpDownloadAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter { public static final String REQUEST_ID_REGEX_PATTERN = ".*\\/downloadId\\/.*"; - private static final Logger LOGGER = LoggerFactory.getLogger(HttpDownloadAuthenticationFilter.class); + private static final Logger LOG = LoggerFactory.getLogger(HttpDownloadAuthenticationFilter.class); private final Pattern pattern; private final Cache cache; @@ -50,7 +50,7 @@ public class HttpDownloadAuthenticationFilter extends AbstractPreAuthenticatedPr if (!matcher.matches()) { return null; } - LOGGER.debug("retrieving id from URI request {}", requestURI); + LOG.debug("retrieving id from URI request {}", requestURI); final String[] groups = requestURI.split("\\/"); final String id = groups[groups.length - 1]; if (id == null) { diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java index d43ae4339..770c8ffcf 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/artifact/MgmtArtifactHash.java @@ -27,6 +27,7 @@ public class MgmtArtifactHash { * Default constructor. */ public MgmtArtifactHash() { + // used for jackson to instantiate } /** diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java index ea6dccc7e..9053af8c8 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadArtifactRestApi.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * */ @RequestMapping(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING) +@FunctionalInterface public interface MgmtDownloadArtifactRestApi { /** diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java index 52cd1c991..ea179b830 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtDownloadRestApi.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.ResponseBody; * */ @RequestMapping(MgmtRestConstants.DOWNLOAD_ID_V1_REQUEST_MAPPING_BASE) +@FunctionalInterface public interface MgmtDownloadRestApi { /** diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java index e99a33c5f..721995d88 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDistributionSetResource.java @@ -39,7 +39,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetWithActionType; -import org.eclipse.hawkbit.tenancy.TenantAware; +import org.eclipse.hawkbit.security.SystemSecurityContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -72,15 +72,15 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { @Autowired private SystemManagement systemManagement; - @Autowired - private TenantAware currentTenant; - @Autowired private EntityFactory entityFactory; @Autowired private DistributionSetManagement distributionSetManagement; + @Autowired + private SystemSecurityContext systemSecurityContext; + @Override public ResponseEntity> getDistributionSets( @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @@ -119,8 +119,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi { LOG.debug("creating {} distribution sets", sets.size()); // set default Ds type if ds type is null - sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(this.systemManagement - .getTenantMetadata(this.currentTenant.getCurrentTenant()).getDefaultDsType().getKey())); + final String defaultDsKey = systemSecurityContext + .runAsSystem(() -> this.systemManagement.getTenantMetadata().getDefaultDsType().getKey()); + sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(defaultDsKey)); final Iterable createdDSets = this.distributionSetManagement .createDistributionSets(MgmtDistributionSetMapper.dsFromRequest(sets, this.softwareManagement, diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java index 87a215183..b6f9f27c8 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtDownloadResource.java @@ -15,6 +15,7 @@ import org.eclipse.hawkbit.artifact.repository.ArtifactRepository; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; import org.eclipse.hawkbit.cache.CacheConstants; import org.eclipse.hawkbit.cache.DownloadArtifactCache; +import org.eclipse.hawkbit.cache.DownloadType; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadRestApi; import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder; import org.slf4j.Logger; @@ -73,14 +74,11 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi { final DownloadArtifactCache artifactCache = (DownloadArtifactCache) cacheWrapper.get(); DbArtifact artifact = null; - switch (artifactCache.getDownloadType()) { - case BY_SHA1: - artifact = artifactRepository.getArtifactBySha1(artifactCache.getId()); - break; - default: + if (DownloadType.BY_SHA1.equals(artifactCache.getDownloadType())) { + artifact = artifactRepository.getArtifactBySha1(artifactCache.getId()); + } else { LOGGER.warn("Download Type {} not supported", artifactCache.getDownloadType()); - break; } if (artifact == null) { diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemMapper.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemMapper.java index d3f78fad2..d0c8dfcc5 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemMapper.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSystemMapper.java @@ -23,7 +23,7 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; * A mapper which maps repository model to RESTful model representation and * back. */ -public class MgmtSystemMapper { +public final class MgmtSystemMapper { private MgmtSystemMapper() { // Utility class @@ -51,6 +51,8 @@ public class MgmtSystemMapper { * maps a TenantConfigurationValue from the repository model to a * MgmtSystemTenantConfigurationValue, the RESTful model. * + * @param key + * the key * @param repoConfValue * configuration value as repository model * @return configuration value as RESTful model diff --git a/hawkbit-repository/hawkbit-repository-api/pom.xml b/hawkbit-repository/hawkbit-repository-api/pom.xml index 050a9a070..e809ce29d 100644 --- a/hawkbit-repository/hawkbit-repository-api/pom.xml +++ b/hawkbit-repository/hawkbit-repository-api/pom.xml @@ -9,16 +9,16 @@ --> - 4.0.0 - - org.eclipse.hawkbit - hawkbit-repository - 0.2.0-SNAPSHOT - - hawkbit-repository-api - hawkBit :: Repository API - - + 4.0.0 + + org.eclipse.hawkbit + hawkbit-repository + 0.2.0-SNAPSHOT + + hawkbit-repository-api + hawkBit :: Repository API + + org.eclipse.hawkbit hawkbit-security-core @@ -36,14 +36,33 @@ cz.jirutka.rsql rsql-parser - + org.springframework.hateoas spring-hateoas - - org.springframework.boot - spring-boot-configuration-processor - true - - + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + ru.yandex.qatools.allure + allure-junit-adaptor + test + + + org.easytesting + fest-assert-core + test + + + org.easytesting + fest-assert + test + + \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java index e5dcb8f74..f06621fd4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java @@ -183,6 +183,8 @@ public interface ControllerManagement { * @return the security context of the target, in case no target exists for * the given controllerId {@code null} is returned */ + @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.HAS_AUTH_READ_TARGET_SEC_TOKEN) String getSecurityTokenByControllerId(@NotEmpty String controllerId); /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java index a2e7e5213..d8a6f54fe 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetManagement.java @@ -24,6 +24,7 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldExc import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetFilter; +import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.DistributionSetTag; import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult; @@ -32,7 +33,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleType; import org.eclipse.hawkbit.repository.model.Tag; import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder; import org.hibernate.validator.constraints.NotEmpty; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -44,9 +44,6 @@ import org.springframework.security.access.prepost.PreAuthorize; */ public interface DistributionSetManagement { - // TODO rename/document the whole with details thing (document what the - // details are and maybe find a better name, e.g. with dependencies?) - /** * Assigns {@link SoftwareModule} to existing {@link DistributionSet}. * @@ -284,6 +281,16 @@ public interface DistributionSetManagement { Page findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId, @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 findDistributionSetMetadataByDistributionSetId(@NotNull Long distributionSetId); + /** * finds all meta data by the given distribution set id. * @@ -320,7 +327,6 @@ public interface DistributionSetManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) List findDistributionSetsAll(Collection dist); - // TODO discuss: use enum instead of the true,false,null switch ? /** * finds all {@link DistributionSet}s. * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java index 0934e871e..03027598e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SoftwareManagement.java @@ -340,6 +340,7 @@ public interface SoftwareManagement { * to search for * @return {@link List} of found {@link SoftwareModule}s */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY) List findSoftwareModulesById(@NotEmpty Collection ids); /** @@ -482,5 +483,23 @@ public interface SoftwareManagement { */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY) 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 findSoftwareModuleMetadataBySoftwareModuleId(Long softwareModuleId); } diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java index a44b13d92..cd414b09a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java @@ -61,6 +61,9 @@ public interface SystemManagement { /** * @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()} */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR + + SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) TenantMetaData getTenantMetadata(); /** @@ -77,6 +80,7 @@ public interface SystemManagement { * to retrieve data for * @return {@link TenantMetaData} of given tenant */ + @PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE) TenantMetaData getTenantMetadata(@NotNull String tenant); /** @@ -86,6 +90,7 @@ public interface SystemManagement { * to update * @return updated {@link TenantMetaData} entity */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) TenantMetaData updateTenantMetadata(@NotNull TenantMetaData metaData); -} \ No newline at end of file +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionCreatedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionCreatedEvent.java new file mode 100644 index 000000000..20515521d --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionCreatedEvent.java @@ -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 { + + private static final long serialVersionUID = 1L; + + /** + * @param distributionSet + * the distributionSet which has been created + */ + public DistributionCreatedEvent(final DistributionSet distributionSet) { + super(distributionSet); + } +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionDeletedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionDeletedEvent.java new file mode 100644 index 000000000..47c8c8435 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionDeletedEvent.java @@ -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; + } +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionSetUpdateEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionSetUpdateEvent.java new file mode 100644 index 000000000..d060e2ee5 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/DistributionSetUpdateEvent.java @@ -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 { + + private static final long serialVersionUID = 1L; + + + /** + * Constructor + * @param ds Distribution Set + */ + public DistributionSetUpdateEvent(final DistributionSet ds) { + super(ds); + } +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutChangeEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutChangeEvent.java index 2ff739726..05960938f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutChangeEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutChangeEvent.java @@ -8,7 +8,7 @@ */ package org.eclipse.hawkbit.repository.eventbus.event; -import org.eclipse.hawkbit.eventbus.event.AbstractEvent; +import org.eclipse.hawkbit.eventbus.event.DefaultEvent; /** * Event declaration for the UI to notify the UI that a rollout has been @@ -17,7 +17,7 @@ import org.eclipse.hawkbit.eventbus.event.AbstractEvent; * @author Michael Hirsch * */ -public class RolloutChangeEvent extends AbstractEvent { +public class RolloutChangeEvent extends DefaultEvent { private final Long rolloutId; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupChangeEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupChangeEvent.java index 5c36ab61f..686625d03 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupChangeEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/RolloutGroupChangeEvent.java @@ -8,7 +8,7 @@ */ package org.eclipse.hawkbit.repository.eventbus.event; -import org.eclipse.hawkbit.eventbus.event.AbstractEvent; +import org.eclipse.hawkbit.eventbus.event.DefaultEvent; /** * Event declaration for the UI to notify the UI that a rollout has been @@ -17,7 +17,7 @@ import org.eclipse.hawkbit.eventbus.event.AbstractEvent; * @author Michael Hirsch * */ -public class RolloutGroupChangeEvent extends AbstractEvent { +public class RolloutGroupChangeEvent extends DefaultEvent { private final Long rolloutId; private final Long rolloutGroupId; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetAssignDistributionSetEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetAssignDistributionSetEvent.java index 077e05462..586a4b9d2 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetAssignDistributionSetEvent.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetAssignDistributionSetEvent.java @@ -11,14 +11,14 @@ package org.eclipse.hawkbit.repository.eventbus.event; import java.net.URI; import java.util.Collection; -import org.eclipse.hawkbit.eventbus.event.AbstractEvent; +import org.eclipse.hawkbit.eventbus.event.DefaultEvent; import org.eclipse.hawkbit.repository.model.SoftwareModule; /** * Event that gets sent when a distribution set gets assigned to a target. * */ -public class TargetAssignDistributionSetEvent extends AbstractEvent { +public class TargetAssignDistributionSetEvent extends DefaultEvent { private final Collection softwareModules; private final String controllerId; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetDeletedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetDeletedEvent.java new file mode 100644 index 000000000..637a0dcc5 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetDeletedEvent.java @@ -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; + } + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetUpdatedEvent.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetUpdatedEvent.java new file mode 100644 index 000000000..8ae5718e9 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/eventbus/event/TargetUpdatedEvent.java @@ -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 { + + private static final long serialVersionUID = 5665118668865832477L; + + /** + * Constructor + * + * @param baseEntity + * Target entity + */ + public TargetUpdatedEvent(final Target baseEntity) { + super(baseEntity); + } + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java index 7b7975d78..c7ed8637e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactDeleteFailedException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if artifact deletion failed. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public final class ArtifactDeleteFailedException extends SpServerRtException { +public final class ArtifactDeleteFailedException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java index d83f80e64..6f762b56c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ArtifactUploadFailedException.java @@ -9,14 +9,14 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * * * */ -public final class ArtifactUploadFailedException extends SpServerRtException { +public final class ArtifactUploadFailedException extends AbstractServerRtException { /** * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java index 0a787e5bb..1afd994cf 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if cancelation of actions is performened where the action is not @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public final class CancelActionNotAllowedException extends SpServerRtException { +public final class CancelActionNotAllowedException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java index c2a3b4456..ec2691e52 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ConcurrentModificationException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * {@link ConcurrentModificationException} is thrown when a given entity in's @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class ConcurrentModificationException extends SpServerRtException { +public class ConcurrentModificationException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_CONCURRENT_MODIFICATION; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetCreationFailedMissingMandatoryModuleException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetCreationFailedMissingMandatoryModuleException.java index 0dc2f9752..936d3e5d2 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetCreationFailedMissingMandatoryModuleException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetCreationFailedMissingMandatoryModuleException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if DS creation failed. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public final class DistributionSetCreationFailedMissingMandatoryModuleException extends SpServerRtException { +public final class DistributionSetCreationFailedMissingMandatoryModuleException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java index d3e10b213..8cf3c6162 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/DistributionSetTypeUndefinedException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType; * * */ -public class DistributionSetTypeUndefinedException extends SpServerRtException { +public class DistributionSetTypeUndefinedException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java index a38ec5bb6..73b14c57a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityAlreadyExistsException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * the {@link EntityAlreadyExistsException} is thrown when a entity is tried to @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class EntityAlreadyExistsException extends SpServerRtException { +public class EntityAlreadyExistsException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_ALRREADY_EXISTS; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityLockedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityLockedException.java index 1d55bdc34..23c372410 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityLockedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityLockedException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * The {@link EntityLockedException} is thrown when an entity has been locked by @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class EntityLockedException extends SpServerRtException { +public class EntityLockedException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_ENTITY_LOCKED; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java index 280436d3b..ce1446f67 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityNotFoundException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * the {@link EntityNotFoundException} is thrown when a entity is tried find but @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class EntityNotFoundException extends SpServerRtException { +public class EntityNotFoundException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_NOT_EXISTS; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java index 7908c4db5..f2686abb1 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/EntityReadOnlyException.java @@ -9,13 +9,13 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * the {@link EntityReadOnlyException} is thrown when a entity is in read only * mode and a user tries to change it. */ -public class EntityReadOnlyException extends SpServerRtException { +public class EntityReadOnlyException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_READ_ONLY; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java index 23b5f7067..83957739a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ForceQuitActionNotAllowedException.java @@ -9,14 +9,14 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown when force quitting an actions is not allowed. e.g. the action is not * active or it is not canceled before. * */ -public final class ForceQuitActionNotAllowedException extends SpServerRtException { +public final class ForceQuitActionNotAllowedException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/GridFSDBFileNotFoundException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/GridFSDBFileNotFoundException.java index d22fe2b6e..3f3c49e03 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/GridFSDBFileNotFoundException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/GridFSDBFileNotFoundException.java @@ -9,14 +9,14 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * * * */ -public final class GridFSDBFileNotFoundException extends SpServerRtException { +public final class GridFSDBFileNotFoundException extends AbstractServerRtException { /** * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java index 51b95afbd..10bc5bba4 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/IncompleteDistributionSetException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if a distribution set is assigned to a a target that is incomplete @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public final class IncompleteDistributionSetException extends SpServerRtException { +public final class IncompleteDistributionSetException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java index e15ba43ee..d3802300a 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InsufficientPermissionException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception which is thrown in case the current security context object does @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class InsufficientPermissionException extends SpServerRtException { +public class InsufficientPermissionException extends AbstractServerRtException { private static final long serialVersionUID = 1L; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java index c08673164..f6083a612 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidMD5HashException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if MD5 checksum check fails. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class InvalidMD5HashException extends SpServerRtException { +public class InvalidMD5HashException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java index e4136cd82..4cc26c571 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidSHA1HashException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if SHA1 checksum check fails. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class InvalidSHA1HashException extends SpServerRtException { +public class InvalidSHA1HashException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java index 70b890483..160d5c07b 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java @@ -9,12 +9,12 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception which is thrown when trying to set an invalid target address. */ -public class InvalidTargetAddressException extends SpServerRtException { +public class InvalidTargetAddressException extends AbstractServerRtException { /** * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiPartFileUploadException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiPartFileUploadException.java index e37786e19..7b554982e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiPartFileUploadException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiPartFileUploadException.java @@ -9,13 +9,13 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if a multi part exception occurred. * */ -public final class MultiPartFileUploadException extends SpServerRtException { +public final class MultiPartFileUploadException extends AbstractServerRtException { private static final long serialVersionUID = 1L; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java index 268ab02ba..d46f6d827 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterSyntaxException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception used by the REST API in case of RSQL search filter query. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class RSQLParameterSyntaxException extends SpServerRtException { +public class RSQLParameterSyntaxException extends AbstractServerRtException { /** * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java index df58ecc8b..402a3eee7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RSQLParameterUnsupportedFieldException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception used by the REST API in case of invalid field name in the rsql @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class RSQLParameterUnsupportedFieldException extends SpServerRtException { +public class RSQLParameterUnsupportedFieldException extends AbstractServerRtException { /** * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java index f2920c18d..2f1937008 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/RolloutIllegalStateException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * the {@link RolloutIllegalStateException} is thrown when a rollout is changing @@ -17,7 +17,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * rollout, or trying to resume a already finished rollout. * */ -public class RolloutIllegalStateException extends SpServerRtException { +public class RolloutIllegalStateException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_ROLLOUT_ILLEGAL_STATE; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java index 95aab39a8..810054e93 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/TenantNotExistException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * the {@link TenantNotExistException} is thrown when e.g. a controller tries to @@ -20,7 +20,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class TenantNotExistException extends SpServerRtException { +public class TenantNotExistException extends AbstractServerRtException { private static final long serialVersionUID = 1L; private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_TENANT_NOT_EXISTS; diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java index 78da0b9f3..6004bc2e7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyAttributeEntriesException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if too many status entries have been inserted. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public final class ToManyAttributeEntriesException extends SpServerRtException { +public final class ToManyAttributeEntriesException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyStatusEntriesException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyStatusEntriesException.java index 5d4367924..7b8f4a1b0 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyStatusEntriesException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/ToManyStatusEntriesException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if too many status entries have been inserted. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public final class ToManyStatusEntriesException extends SpServerRtException { +public final class ToManyStatusEntriesException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java index 3726e3188..2ed76dfbc 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/UnsupportedSoftwareModuleForThisDistributionSetException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.repository.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -23,7 +23,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; * * */ -public class UnsupportedSoftwareModuleForThisDistributionSetException extends SpServerRtException { +public class UnsupportedSoftwareModuleForThisDistributionSetException extends AbstractServerRtException { /** * */ diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/EntityInterceptor.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/EntityInterceptor.java new file mode 100644 index 000000000..b6fff3f91 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/EntityInterceptor.java @@ -0,0 +1,79 @@ +/** + * 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.model; + +/** + * Interface for the entity interceptor lifecycle. + */ +public interface EntityInterceptor { + + /** + * Callback for the {@link @PrePersist} lifecycle event. + * + * @param entity + * the model entity + */ + default void prePersist(final Object entity) { + }; + + /** + * Callback for the {@link @PostPersist} lifecycle event. + * + * @param entity + * the model entity + */ + default void postPersist(final Object entity) { + }; + + /** + * Callback for the {@link @PostRemove} lifecycle event. + * + * @param entity + * the model entity + */ + default void postRemove(final Object entity) { + }; + + /** + * Callback for the {@link @PreRemove} lifecycle event. + * + * @param entity + * the model entity + */ + default void preRemove(final Object entity) { + }; + + /** + * Callback for the {@link @PostLoad} lifecycle event. + * + * @param entity + * the model entity + */ + default void postLoad(final Object entity) { + }; + + /** + * Callback for the {@link @PreUpdate} lifecycle event. + * + * @param entity + * the model entity + */ + default void preUpdate(final Object entity) { + }; + + /** + * Callback for the {@link @PostUpdate} lifecycle event. + * + * @param entity + * the model entity + */ + default void postUpdate(final Object entity) { + }; + +} diff --git a/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java new file mode 100644 index 000000000..1a0d85d30 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/test/java/org/eclipse/hawkbit/repository/RepositoryManagementMethodPreAuthorizeAnnotatedTest.java @@ -0,0 +1,97 @@ +/** + * 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; + +import static org.fest.assertions.Assertions.assertThat; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.junit.Test; +import org.springframework.security.access.prepost.PreAuthorize; + +import com.google.common.reflect.ClassPath; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +@Features("Unit Tests - Repository") +@Stories("Security Test") +public class RepositoryManagementMethodPreAuthorizeAnnotatedTest { + + private static final Set METHOD_SECURITY_EXCLUSION = new HashSet<>(); + + static { + METHOD_SECURITY_EXCLUSION.add(getMethod(SystemManagement.class, "currentTenant")); + } + + @Test + @Description("Verfies that repository methods are @PreAuthorize annotated") + public void repositoryManagementMethodsArePreAuthorizedAnnotated() + throws ClassNotFoundException, URISyntaxException, IOException { + final List> findInterfacesInPackage = findInterfacesInPackage(getClass().getPackage(), + Pattern.compile(".*Management")); + + assertThat(findInterfacesInPackage).isNotEmpty(); + for (final Class interfaceToCheck : findInterfacesInPackage) { + assertDeclaredMethodsContainsPreAuthorizeAnnotaions(interfaceToCheck); + } + + // all exclusion should be used, otherwise the method exlusion should be + // cleaned up again + assertThat(METHOD_SECURITY_EXCLUSION).isEmpty(); + } + + /** + * asserts that the given methods are annotated with the + * {@link PreAuthorize} annotation for security. Inherited methods are not + * checked. The following methods are excluded due inherited from + * {@link Object}, like equals() or toString(). + * + * @param clazz + * the class to retrieve the public declared methods + */ + private static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class clazz) { + final Method[] declaredMethods = clazz.getDeclaredMethods(); + for (final Method method : declaredMethods) { + final boolean methodExcluded = METHOD_SECURITY_EXCLUSION.contains(method); + if (methodExcluded || method.isSynthetic() || Modifier.isPublic(method.getModifiers())) { + // skip method because it should be excluded + METHOD_SECURITY_EXCLUSION.remove(method); + continue; + } + final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class); + assertThat(annotation).as("The public method " + method.getName() + " in class " + clazz.getName() + + " is not annoated with @PreAuthorize, security leak?").isNotNull(); + } + } + + private List> findInterfacesInPackage(final Package p, final Pattern includeFilter) + throws URISyntaxException, IOException, ClassNotFoundException { + return ClassPath.from(Thread.currentThread().getContextClassLoader()).getTopLevelClasses(p.getName()).stream() + .filter(clazzInfo -> includeFilter.matcher(clazzInfo.getSimpleName()).matches()) + .map(clazzInfo -> clazzInfo.load()).filter(clazz -> clazz.isInterface()).collect(Collectors.toList()); + } + + private static Method getMethod(final Class clazz, final String methodName, final Class... parameterTypes) { + try { + return clazz.getMethod(methodName, parameterTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException(e.getMessage(), e); + } + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java index 19f7b9e0f..a62de9a06 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java @@ -46,6 +46,7 @@ import org.eclipse.hawkbit.repository.jpa.aspects.ExceptionMappingAspectHandler; import org.eclipse.hawkbit.repository.jpa.configuration.MultiTenantJpaTransactionManager; import org.eclipse.hawkbit.repository.jpa.model.helper.AfterTransactionCommitExecutorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.CacheManagerHolder; +import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.SystemManagementHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; @@ -144,6 +145,14 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { return SecurityTokenGeneratorHolder.getInstance(); } + /** + * @return the singleton instance of the {@link EntityInterceptorHolder} + */ + @Bean + public EntityInterceptorHolder entityInterceptorHolder() { + return EntityInterceptorHolder.getInstance(); + } + /** * @return the singleton instance of the {@link CacheManagerHolder} */ diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java index 0e97d6ff5..8736fefd7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDistributionSetManagement.java @@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.DistributionSetMetadataFields; import org.eclipse.hawkbit.repository.DistributionSetTypeFields; import org.eclipse.hawkbit.repository.SystemManagement; 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.exception.EntityAlreadyExistsException; 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.DistributionSetType; import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -102,6 +104,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Autowired private AfterTransactionCommitExecutor afterCommit; + @Autowired + private TenantAware tenantAware; + @Override public DistributionSet findDistributionSetByIdWithDetails(final Long distid) { return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid)); @@ -193,6 +198,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { // handle the empty list distributionSetRepository.deleteByIdIn(toHardDelete); } + + Arrays.stream(distributionSetIDs) + .forEach(dsId -> eventBus.post(new DistributionDeletedEvent(tenantAware.getCurrentTenant(), dsId))); } @Override @@ -475,11 +483,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { if (distributionSetMetadataRepository.exists(metadata.getId())) { throwMetadataKeyAlreadyExists(metadata.getId().getKey()); } - // 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) metadata.getDistributionSet()).setLastModifiedAt(0L); + + touch(metadata.getDistributionSet()); return distributionSetMetadataRepository.save(metadata); } @@ -494,7 +499,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { for (final JpaDistributionSetMetadata distributionSetMetadata : metadata) { checkAndThrowAlreadyIfDistributionSetMetadataExists(distributionSetMetadata.getId()); } - metadata.forEach(m -> entityManager.merge((JpaDistributionSet) m.getDistributionSet()).setLastModifiedAt(0L)); + metadata.forEach(m -> touch(m.getDistributionSet())); return new ArrayList<>( (Collection) distributionSetMetadataRepository.save(metadata)); @@ -510,7 +515,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { findOne(metadata.getDistributionSet(), metadata.getKey()); // touch it to update the lock revision because we are modifying the // DS indirectly - entityManager.merge((JpaDistributionSet) metadata.getDistributionSet()).setLastModifiedAt(0L); + touch(metadata.getDistributionSet());; return distributionSetMetadataRepository.save(metadata); } @@ -518,13 +523,26 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { @Transactional(isolation = Isolation.READ_UNCOMMITTED) @Modifying public void deleteDistributionSetMetadata(final DistributionSet distributionSet, final String key) { + touch(distributionSet); 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 public Page findDistributionSetMetadataByDistributionSetId(final Long distributionSetId, final Pageable pageable) { - return convertMdPage(distributionSetMetadataRepository .findAll((Specification) (root, query, cb) -> cb.equal( root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), @@ -532,6 +550,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement { pageable); } + @Override + public List findDistributionSetMetadataByDistributionSetId(final Long distributionSetId) { + return new ArrayList(distributionSetMetadataRepository + .findAll((Specification) (root, query, cb) -> cb.equal( + root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), + distributionSetId))); + } + @Override public Page findDistributionSetMetadataByDistributionSetId(final Long distributionSetId, final String rsqlParam, final Pageable pageable) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java index b561667a9..3f8c1a54b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaSoftwareManagement.java @@ -621,6 +621,16 @@ public class JpaSoftwareManagement implements SoftwareManagement { pageable); } + @Override + public List findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId) { + return new ArrayList<>( + softwareModuleMetadataRepository + .findAll((Specification) (root, query, + cb) -> cb.and(cb.equal( + root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), + softwareModuleId)))); + } + @Override public SoftwareModuleMetadata findSoftwareModuleMetadata(final SoftwareModule softwareModule, final String key) { return findSoftwareModuleMetadata(new SwMetadataCompositeKey(softwareModule, key)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java index 1cd2ffc3c..225c0b4b2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java @@ -29,6 +29,7 @@ import javax.persistence.criteria.Root; import org.eclipse.hawkbit.repository.TargetFields; 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.exception.EntityAlreadyExistsException; 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.TargetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; +import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.data.domain.Page; @@ -94,6 +96,9 @@ public class JpaTargetManagement implements TargetManagement { @Autowired private EventBus eventBus; + @Autowired + private TenantAware tenantAware; + @Autowired private AfterTransactionCommitExecutor afterCommit; @@ -206,6 +211,8 @@ public class JpaTargetManagement implements TargetManagement { targetInfoRepository.deleteByTargetIdIn(targetsForCurrentTenant); targetRepository.deleteByIdIn(targetsForCurrentTenant); } + targetsForCurrentTenant + .forEach(targetId -> eventBus.post(new TargetDeletedEvent(tenantAware.getCurrentTenant(), targetId))); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/eventbus/EntityChangeEventListener.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/eventbus/EntityChangeEventListener.java deleted file mode 100644 index 5f41063d2..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/eventbus/EntityChangeEventListener.java +++ /dev/null @@ -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 targetIds = (Collection) 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) 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(); - } - -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java index 257828c6f..ef1868c3f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/AbstractJpaBaseEntity.java @@ -31,7 +31,8 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; */ @MappedSuperclass @Access(AccessType.FIELD) -@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class }) +@EntityListeners({ AuditingEntityListener.class, CacheFieldEntityListener.class, EntityPropertyChangeListener.class, + EntityInterceptorListener.class }) public abstract class AbstractJpaBaseEntity implements BaseEntity { private static final long serialVersionUID = 1L; @@ -178,4 +179,5 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity { return true; } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListener.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListener.java new file mode 100644 index 000000000..75f1411ef --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListener.java @@ -0,0 +1,110 @@ +/** + * 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 java.util.function.Consumer; + +import javax.persistence.PostLoad; +import javax.persistence.PostPersist; +import javax.persistence.PostRemove; +import javax.persistence.PostUpdate; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; +import org.eclipse.hawkbit.repository.model.EntityInterceptor; + +/** + * Entity listener which calls the callback's of all registered entity + * interceptors. + */ +public class EntityInterceptorListener { + + /** + * Callback for lifecyle event pre persist. + * + * @param entity + * the JPA entity which this listener is associated with + */ + @PrePersist + public void prePersist(final Object entity) { + notifyAll(interceptor -> interceptor.prePersist(entity)); + } + + /** + * Callback for lifecyle event post persist. + * + * @param entity + * the JPA entity which this listener is associated with + */ + @PostPersist + public void postPersist(final Object entity) { + notifyAll(interceptor -> interceptor.postPersist(entity)); + } + + /** + * Callback for lifecyle event post remove. + * + * @param entity + * the JPA entity which this listener is associated with + */ + @PostRemove + public void postRemove(final Object entity) { + notifyAll(interceptor -> interceptor.postRemove(entity)); + } + + /** + * Callback for lifecyle event pre remove. + * + * @param entity + * the JPA entity which this listener is associated with + */ + @PreRemove + public void preRemove(final Object entity) { + notifyAll(interceptor -> interceptor.preRemove(entity)); + } + + /** + * Callback for lifecyle event post load. + * + * @param entity + * the JPA entity which this listener is associated with + */ + @PostLoad + public void postLoad(final Object entity) { + notifyAll(interceptor -> interceptor.postLoad(entity)); + } + + /** + * Callback for lifecyle event pre update. + * + * @param entity + * the JPA entity which this listener is associated with + */ + @PreUpdate + public void preUpdate(final Object entity) { + notifyAll(interceptor -> interceptor.preUpdate(entity)); + } + + /** + * Callback for lifecyle event post update. + * + * @param entity + * the JPA entity which this listener is associated with + */ + @PostUpdate + public void postUpdate(final Object entity) { + notifyAll(interceptor -> interceptor.postUpdate(entity)); + } + + private static void notifyAll(final Consumer action) { + EntityInterceptorHolder.getInstance().getEntityInterceptors().forEach(action); + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java index 2dd0fdb40..27fbc687e 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EntityPropertyChangeListener.java @@ -8,79 +8,47 @@ */ 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.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.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 { @Override public void postInsert(final DescriptorEvent event) { - if (event.getObject().getClass().equals(Action.class)) { - final Action action = (Action) event.getObject(); - if (action.getRollout() != null) { - final EventBus eventBus = getEventBus(); - final AfterTransactionCommitExecutor afterCommit = getAfterTransactionCommmitExecutor(); - afterCommit.afterCommit(() -> eventBus.post(new ActionCreatedEvent(action))); - } + final Object object = event.getObject(); + if (isEventAwareEntity(object)) { + doNotifiy(() -> ((EventAwareEntity) object).fireCreateEvent(event)); } - } @Override public void postUpdate(final DescriptorEvent event) { - if (event.getObject().getClass().equals(JpaAction.class)) { - getAfterTransactionCommmitExecutor().afterCommit(() -> getEventBus().post( - new ActionPropertyChangeEvent((Action) event.getObject(), getChangeSet(Action.class, 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)))); + final Object object = event.getObject(); + if (isEventAwareEntity(object)) { + doNotifiy(() -> ((EventAwareEntity) object).fireUpdateEvent(event)); } } - private Map.Values> getChangeSet( - final Class 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 AbstractPropertyChangeEvent(rolloutGroup, null).new Values( - record.getOldValue(), record.getNewValue()))); + @Override + public void postDelete(final DescriptorEvent event) { + final Object object = event.getObject(); + if (isEventAwareEntity(object)) { + doNotifiy(() -> ((EventAwareEntity) object).fireDeleteEvent(event)); + } } - private AfterTransactionCommitExecutor getAfterTransactionCommmitExecutor() { - return AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit(); + private boolean isEventAwareEntity(final Object object) { + return object instanceof EventAwareEntity; } - private EventBus getEventBus() { - return EventBusHolder.getInstance().getEventBus(); + private void doNotifiy(final Runnable runnable) { + AfterTransactionCommitExecutorHolder.getInstance().getAfterCommit().afterCommit(runnable); } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java new file mode 100644 index 000000000..889a61796 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/EventAwareEntity.java @@ -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); +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java index 5fa2c3bed..72ef46ba3 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java @@ -28,6 +28,10 @@ import javax.persistence.NamedSubgraph; import javax.persistence.OneToMany; 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.ActionStatus; 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.Target; import org.eclipse.persistence.annotations.CascadeOnDelete; +import org.eclipse.persistence.descriptors.DescriptorEvent; /** * 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 // sub entities @SuppressWarnings("squid:S2160") -public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action { +public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Action, EventAwareEntity { private static final long serialVersionUID = 1L; @ManyToOne(fetch = FetchType.LAZY) @@ -171,4 +176,20 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio 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 + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index 676215424..0fa2d0c33 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -33,8 +34,14 @@ import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.eclipse.hawkbit.repository.eventbus.event.AbstractPropertyChangeEvent; +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.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.DistributionSet; 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.TargetInfo; import org.eclipse.persistence.annotations.CascadeOnDelete; +import org.eclipse.persistence.descriptors.DescriptorEvent; /** * 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 // sub entities @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 String COMPLETE_PROPERTY = "complete"; + + private static final String DELETED_PROPERTY = "deleted"; + @Column(name = "required_migration_step") private boolean requiredMigrationStep; @@ -279,4 +291,30 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen 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.Values> 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())); + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java index 3cbe65717..85395e27b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRollout.java @@ -25,13 +25,17 @@ import javax.persistence.Table; import javax.persistence.Transient; 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.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.DistributionSet; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; +import org.eclipse.persistence.descriptors.DescriptorEvent; /** * 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 // sub entities @SuppressWarnings("squid:S2160") -public class JpaRollout extends AbstractJpaNamedEntity implements Rollout { +public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, EventAwareEntity { private static final long serialVersionUID = 1L; @@ -197,4 +201,21 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout { + ", 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 + } + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java index 79da6630a..9bb8644f4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaRolloutGroup.java @@ -25,9 +25,13 @@ import javax.persistence.Table; import javax.persistence.Transient; 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.RolloutGroup; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; +import org.eclipse.persistence.descriptors.DescriptorEvent; /** * 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 // sub entities @SuppressWarnings("squid:S2160") -public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup { +public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGroup, EventAwareEntity { private static final long serialVersionUID = 1L; @@ -236,4 +240,19 @@ public class JpaRolloutGroup extends AbstractJpaNamedEntity implements RolloutGr + ", 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 + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java index 183405470..c91247321 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTarget.java @@ -36,6 +36,10 @@ import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; 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.SecurityTokenGeneratorHolder; 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.TargetTag; import org.eclipse.persistence.annotations.CascadeOnDelete; +import org.eclipse.persistence.descriptors.DescriptorEvent; import org.springframework.data.domain.Persistable; /** @@ -64,7 +69,7 @@ import org.springframework.data.domain.Persistable; // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // sub entities @SuppressWarnings("squid:S2160") -public class JpaTarget extends AbstractJpaNamedEntity implements Persistable, Target { +public class JpaTarget extends AbstractJpaNamedEntity implements Persistable, Target, EventAwareEntity { private static final long serialVersionUID = 1L; @Column(name = "controller_id", length = 64) @@ -222,6 +227,7 @@ public class JpaTarget extends AbstractJpaNamedEntity implements Persistable, TargetInfo { +@EntityListeners(EntityPropertyChangeListener.class) +public class JpaTargetInfo implements Persistable, TargetInfo, EventAwareEntity { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(TargetInfo.class); @@ -321,4 +326,19 @@ public class JpaTargetInfo implements Persistable, TargetInfo { } 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 + } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityInterceptorHolder.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityInterceptorHolder.java new file mode 100644 index 000000000..c374f219a --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityInterceptorHolder.java @@ -0,0 +1,43 @@ +/** + * 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.ArrayList; +import java.util.List; + +import org.eclipse.hawkbit.repository.model.EntityInterceptor; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * A singleton bean which holds the {@link EntityInterceptor} to have all + * interceptors in spring beans. + * + */ +public final class EntityInterceptorHolder { + + private static final EntityInterceptorHolder SINGLETON = new EntityInterceptorHolder(); + + @Autowired(required = false) + private final List entityInterceptors = new ArrayList<>(); + + private EntityInterceptorHolder() { + + } + + /** + * @return the entity intreceptor holder singleton instance + */ + public static EntityInterceptorHolder getInstance() { + return SINGLETON; + } + + public List getEntityInterceptors() { + return entityInterceptors; + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java new file mode 100644 index 000000000..2be398e24 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/helper/EntityPropertyChangeHelper.java @@ -0,0 +1,46 @@ +/** + * 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; +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 + */ +public class EntityPropertyChangeHelper { + + /** + * To get the map of entity property change set + * + * @param clazz + * @param event + * @return the map of the changeSet + */ + public static Map.Values> getChangeSet( + final Class 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 AbstractPropertyChangeEvent(rolloutGroup, null).new Values( + record.getOldValue(), record.getNewValue()))); + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/MethodSecurityUtil.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/MethodSecurityUtil.java deleted file mode 100644 index 032289e87..000000000 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/MethodSecurityUtil.java +++ /dev/null @@ -1,63 +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; - -import static org.fest.assertions.Assertions.assertThat; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.Set; - -import org.springframework.security.access.prepost.PreAuthorize; - -public class MethodSecurityUtil { - - private static final Set METHOD_SECURITY_EXCLUSION = new HashSet<>(); - - static { - METHOD_SECURITY_EXCLUSION.add("equals"); - METHOD_SECURITY_EXCLUSION.add("toString"); - METHOD_SECURITY_EXCLUSION.add("hashCode"); - METHOD_SECURITY_EXCLUSION.add("clone"); - METHOD_SECURITY_EXCLUSION.add("setEnvironment"); - // this method shouldn't be public on the DeploymentManagemeht but it is - METHOD_SECURITY_EXCLUSION.add("setOverrideObsoleteUpdateActions"); - METHOD_SECURITY_EXCLUSION.add("isOverrideObsoleteUpdateActions"); - // this method must be public accessible without security because it's - // necessary to acccess - // the security-token of a target without being authenticated because - // the security-token is - // the authentication process - // ControllerManagement#getSecurityTokenByControllerId() - METHOD_SECURITY_EXCLUSION.add("getSecurityTokenByControllerId"); - } - - /** - * asserts that the given methods are annotated with the - * {@link PreAuthorize} annotation for security. Inherited methods are not - * checked. The following methods are excluded due inherited from - * {@link Object}, like equals() or toString(). - * - * @param clazz - * the class to retrieve the public declared methods - */ - public static void assertDeclaredMethodsContainsPreAuthorizeAnnotaions(final Class clazz) { - final Method[] declaredMethods = clazz.getDeclaredMethods(); - for (final Method method : declaredMethods) { - if (!METHOD_SECURITY_EXCLUSION.contains(method.getName()) && !method.isSynthetic() - && Modifier.isPublic(method.getModifiers())) { - final PreAuthorize annotation = method.getAnnotation(PreAuthorize.class); - assertThat(annotation).as( - "The public method " + method.getName() + " is not annoated with @PreAuthorize, security leak?") - .isNotNull(); - } - } - } -} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java index 381e9722d..a23ada6e6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/RolloutManagementTest.java @@ -34,13 +34,13 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorAction import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondition; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus; import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition; -import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus; +import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Description; @@ -56,9 +56,6 @@ import ru.yandex.qatools.allure.annotations.Stories; /** * Junit tests for RolloutManagment. - * - * @author Michael Hirsch - * */ @Features("Component Tests - Repository") @Stories("Rollout Management") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java index a9f004a73..ac2b30d23 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/SystemManagementTest.java @@ -14,10 +14,10 @@ import java.io.ByteArrayInputStream; import java.util.List; import java.util.Random; +import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; -import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.report.model.TenantUsage; import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule; import org.junit.Test; @@ -30,15 +30,6 @@ import ru.yandex.qatools.allure.annotations.Stories; @Stories("System Management") public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB { - @Test - @Description("Ensures that you can create a tenant without setting the necessary security context which holds a current tenant") - public void createInitialTenantWithoutSecurityContext() { - securityRule.clear(); - final String tenantToBeCreated = "newTenantToCreate"; - final TenantMetaData tenantMetadata = systemManagement.getTenantMetadata(tenantToBeCreated); - assertThat(tenantMetadata).isNotNull(); - } - @Test @Description("Ensures that findTenants returns all tenants and not only restricted to the tenant which currently is logged in") public void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() throws Exception { @@ -109,26 +100,27 @@ public class SystemManagementTest extends AbstractJpaIntegrationTestWithMongoDB for (int i = 0; i < tenants; i++) { final String tenantname = "tenant" + i; - securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname), () -> { - systemManagement.getTenantMetadata(tenantname); - if (artifactSize > 0) { - createTestArtifact(random); - createDeletedTestArtifact(random); - } - if (targets > 0) { - final List createdTargets = createTestTargets(targets); - if (updates > 0) { - for (int x = 0; x < updates; x++) { - final DistributionSet ds = testdataFactory.createDistributionSet("to be deployed" + x, - true); - - deploymentManagement.assignDistributionSet(ds, createdTargets); + securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname, true, true, + SpringEvalExpressions.SYSTEM_ROLE), () -> { + systemManagement.getTenantMetadata(tenantname); + if (artifactSize > 0) { + createTestArtifact(random); + createDeletedTestArtifact(random); } - } - } + if (targets > 0) { + final List createdTargets = createTestTargets(targets); + if (updates > 0) { + for (int x = 0; x < updates; x++) { + final DistributionSet ds = testdataFactory + .createDistributionSet("to be deployed" + x, true); - return null; - }); + deploymentManagement.assignDistributionSet(ds, createdTargets); + } + } + } + + return null; + }); } return random; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/eventbus/RepositoryEntityEventTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/eventbus/RepositoryEntityEventTest.java new file mode 100644 index 000000000..0aa305d52 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/eventbus/RepositoryEntityEventTest.java @@ -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 queue = new LinkedBlockingQueue<>(); + + @Subscribe + public void onEvent(final Event event) { + queue.offer(event); + } + + public T waitForEvent(final Class 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; + } + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java new file mode 100644 index 000000000..c3db7ab76 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/model/EntityInterceptorListenerTest.java @@ -0,0 +1,186 @@ +/** + * 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 static org.fest.assertions.Assertions.assertThat; + +import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest; +import org.eclipse.hawkbit.repository.jpa.model.helper.EntityInterceptorHolder; +import org.eclipse.hawkbit.repository.model.EntityInterceptor; +import org.eclipse.hawkbit.repository.model.SoftwareModuleType; +import org.eclipse.hawkbit.repository.model.Target; +import org.junit.Test; + +import ru.yandex.qatools.allure.annotations.Description; +import ru.yandex.qatools.allure.annotations.Features; +import ru.yandex.qatools.allure.annotations.Stories; + +/** + * Test the entity listener interceptor. + */ +@Features("Component Tests - Repository") +@Stories("Entity Listener Interceptor") +public class EntityInterceptorListenerTest extends AbstractJpaIntegrationTest { + + @Override + public void after() { + EntityInterceptorHolder.getInstance().getEntityInterceptors().clear(); + super.after(); + } + + @Test + @Description("Verfies that the pre persist is called after a entity creation.") + public void prePersistIsCalledWhenPersistingATarget() { + executePersistAndAssertCallbackResult(new PrePersistEntityListener()); + } + + @Test + @Description("Verfies that the post persist is called after a entity creation.") + public void postPersistIsCalledWhenPersistingATarget() { + executePersistAndAssertCallbackResult(new PostPersistEntityListener()); + } + + @Test + @Description("Verfies that the post load is called after a entity is loaded.") + public void postLoadIsCalledWhenLoadATarget() { + final PostLoadEntityListener postLoadEntityListener = new PostLoadEntityListener(); + EntityInterceptorHolder.getInstance().getEntityInterceptors().add(postLoadEntityListener); + + final Target targetToBeCreated = entityFactory.generateTarget("targetToBeCreated"); + + targetManagement.createTarget(targetToBeCreated); + + final Target loadedTarget = targetManagement.findTargetByControllerID(targetToBeCreated.getControllerId()); + assertThat(postLoadEntityListener.getEntity()).isNotNull(); + assertThat(postLoadEntityListener.getEntity()).isEqualTo(loadedTarget); + } + + @Test + @Description("Verfies that the pre update is called after a entity update.") + public void preUpdateIsCalledWhenUpdateATarget() { + executeUpdateAndAssertCallbackResult(new PreUpdateEntityListener()); + } + + @Test + @Description("Verfies that the post update is called after a entity update.") + public void postUpdateIsCalledWhenUpdateATarget() { + executeUpdateAndAssertCallbackResult(new PostUpdateEntityListener()); + } + + @Test + @Description("Verfies that the pre remove is called after a entity deletion.") + public void preRemoveIsCalledWhenDeletingATarget() { + executeDeleteAndAssertCallbackResult(new PreRemoveEntityListener()); + } + + @Test + @Description("Verfies that the post remove is called after a entity deletion.") + public void postRemoveIsCalledWhenDeletingATarget() { + executeDeleteAndAssertCallbackResult(new PostRemoveEntityListener()); + } + + private void executePersistAndAssertCallbackResult(final AbstractEntityListener entityInterceptor) { + final Target targetToBeCreated = entityFactory.generateTarget("targetToBeCreated"); + addListenerAndCreateTarget(entityInterceptor, targetToBeCreated); + + assertThat(entityInterceptor.getEntity()).isNotNull(); + assertThat(entityInterceptor.getEntity()).isEqualTo(targetToBeCreated); + } + + private void executeUpdateAndAssertCallbackResult(final AbstractEntityListener entityInterceptor) { + Target updateTarget = addListenerAndCreateTarget(entityInterceptor, + entityFactory.generateTarget("targetToBeCreated")); + updateTarget.setDescription("New"); + + updateTarget = targetManagement.updateTarget(updateTarget); + + assertThat(entityInterceptor.getEntity()).isNotNull(); + assertThat(entityInterceptor.getEntity()).isEqualTo(updateTarget); + } + + private void executeDeleteAndAssertCallbackResult(final AbstractEntityListener entityInterceptor) { + EntityInterceptorHolder.getInstance().getEntityInterceptors().add(entityInterceptor); + final SoftwareModuleType type = softwareManagement + .createSoftwareModuleType(entityFactory.generateSoftwareModuleType("test", "test", "test", 1)); + + softwareManagement.deleteSoftwareModuleType(type); + assertThat(entityInterceptor.getEntity()).isNotNull(); + assertThat(entityInterceptor.getEntity()).isEqualTo(type); + } + + private Target addListenerAndCreateTarget(final AbstractEntityListener entityInterceptor, + final Target targetToBeCreated) { + EntityInterceptorHolder.getInstance().getEntityInterceptors().add(entityInterceptor); + return targetManagement.createTarget(targetToBeCreated); + } + + private static abstract class AbstractEntityListener implements EntityInterceptor { + + private Object entity; + + public Object getEntity() { + return entity; + } + + public void setEntity(final Object entity) { + this.entity = entity; + } + } + + private static class PrePersistEntityListener extends AbstractEntityListener { + @Override + public void prePersist(final Object entity) { + setEntity(entity); + } + } + + private static class PostPersistEntityListener extends AbstractEntityListener { + @Override + public void postPersist(final Object entity) { + setEntity(entity); + } + + } + + private static class PostLoadEntityListener extends AbstractEntityListener { + @Override + public void postLoad(final Object entity) { + setEntity(entity); + } + + } + + private static class PreUpdateEntityListener extends AbstractEntityListener { + @Override + public void preUpdate(final Object entity) { + setEntity(entity); + } + } + + private static class PostUpdateEntityListener extends AbstractEntityListener { + @Override + public void postUpdate(final Object entity) { + setEntity(entity); + } + } + + private static class PreRemoveEntityListener extends AbstractEntityListener { + @Override + public void preRemove(final Object entity) { + setEntity(entity); + } + } + + private static class PostRemoveEntityListener extends AbstractEntityListener { + @Override + public void postRemove(final Object entity) { + setEntity(entity); + } + } +} \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/BaseEntityMatcher.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/BaseEntityMatcher.java index cb3f5476f..c83ae8ad1 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/BaseEntityMatcher.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/matcher/BaseEntityMatcher.java @@ -17,7 +17,7 @@ import org.hamcrest.Matchers; /** * Matcher for {@link BaseEntity}. */ -public class BaseEntityMatcher { +public final class BaseEntityMatcher { private BaseEntityMatcher() { } diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java index 081cedeca..b8c99b57a 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java @@ -8,6 +8,9 @@ */ package org.eclipse.hawkbit.repository.test.util; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE; +import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE; + import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter; import org.eclipse.hawkbit.TestConfiguration; import org.eclipse.hawkbit.repository.ArtifactManagement; @@ -60,7 +63,7 @@ import org.springframework.web.context.WebApplicationContext; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ActiveProfiles({ "test" }) -@WithUser(principal = "bumlux", allSpPermissions = true, authorities = "ROLE_CONTROLLER") +@WithUser(principal = "bumlux", allSpPermissions = true, authorities = { CONTROLLER_ROLE, SYSTEM_ROLE }) @SpringApplicationConfiguration(classes = { TestConfiguration.class }) // destroy the context after each test class because otherwise we get problem // when context is @@ -226,7 +229,7 @@ public abstract class AbstractIntegrationTest implements EnvironmentAware { createTestdatabaseAndStart(); } - private static void createTestdatabaseAndStart() { + private static synchronized void createTestdatabaseAndStart() { if ("MYSQL".equals(System.getProperty("spring.jpa.database"))) { tesdatabase = new CIMySqlTestDatabase(); tesdatabase.before(); diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java index eae0b9a7d..7d7908d6e 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/JpaTestRepositoryManagement.java @@ -13,11 +13,14 @@ import java.util.List; import org.eclipse.hawkbit.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.security.SystemSecurityContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; public class JpaTestRepositoryManagement implements TestRepositoryManagement { + private static final Logger LOGGER = LoggerFactory.getLogger(JpaTestRepositoryManagement.class); @Autowired private TenantAwareCacheManager cacheManager; @@ -28,6 +31,7 @@ public class JpaTestRepositoryManagement implements TestRepositoryManagement { private SystemManagement systemManagement; @Override + @Transactional public void clearTestRepository() { deleteAllRepos(); cacheManager.getDirectCacheNames().forEach(name -> cacheManager.getDirectCache(name).clear()); @@ -43,7 +47,7 @@ public class JpaTestRepositoryManagement implements TestRepositoryManagement { return null; }); } catch (final Exception e) { - e.printStackTrace(); + LOGGER.error("Error hile delete tenant", e); } }); } diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java index 81e2c1daf..34031639d 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java @@ -10,10 +10,10 @@ package org.eclipse.hawkbit.repository.test.util; import java.io.InputStream; import java.nio.charset.Charset; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Random; import java.util.UUID; import org.apache.commons.io.IOUtils; @@ -191,16 +191,17 @@ public class TestdataFactory { public DistributionSet createDistributionSet(final String prefix, final String version, final boolean isRequiredMigrationStep) { - final SoftwareModule appMod = softwareManagement.createSoftwareModule(entityFactory.generateSoftwareModule( - findOrCreateSoftwareModuleType(SM_TYPE_APP, Integer.MAX_VALUE), prefix + SM_TYPE_APP, - version + "." + new Random().nextInt(100), LOREM.words(20), prefix + " vendor Limited, California")); + final SoftwareModule appMod = softwareManagement.createSoftwareModule( + entityFactory.generateSoftwareModule(findOrCreateSoftwareModuleType(SM_TYPE_APP, Integer.MAX_VALUE), + prefix + SM_TYPE_APP, version + "." + new SecureRandom().nextInt(100), LOREM.words(20), + prefix + " vendor Limited, California")); final SoftwareModule runtimeMod = softwareManagement .createSoftwareModule(entityFactory.generateSoftwareModule(findOrCreateSoftwareModuleType(SM_TYPE_RT), - prefix + "app runtime", version + "." + new Random().nextInt(100), LOREM.words(20), + prefix + "app runtime", version + "." + new SecureRandom().nextInt(100), LOREM.words(20), prefix + " vendor GmbH, Stuttgart, Germany")); final SoftwareModule osMod = softwareManagement .createSoftwareModule(entityFactory.generateSoftwareModule(findOrCreateSoftwareModuleType(SM_TYPE_OS), - prefix + " Firmware", version + "." + new Random().nextInt(100), LOREM.words(20), + prefix + " Firmware", version + "." + new SecureRandom().nextInt(100), LOREM.words(20), prefix + " vendor Limited Inc, California")); return distributionSetManagement diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java index a2bc90555..ce5c39843 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/WithSpringAuthorityRule.java @@ -28,16 +28,12 @@ import org.springframework.security.core.context.SecurityContextHolder; public class WithSpringAuthorityRule implements TestRule { - /* - * (non-Javadoc) - * - * @see org.junit.rules.TestRule#apply(org.junit.runners.model.Statement, - * org.junit.runner.Description) - */ @Override public Statement apply(final Statement base, final Description description) { return new Statement() { @Override + // throwable comes from jnuit evaluate signature + @SuppressWarnings("squid:S00112") public void evaluate() throws Throwable { final SecurityContext oldContext = before(description); try { @@ -49,33 +45,28 @@ public class WithSpringAuthorityRule implements TestRule { }; } - private SecurityContext before(final Description description) throws Throwable { + private SecurityContext before(final Description description) { final SecurityContext oldContext = SecurityContextHolder.getContext(); WithUser annotation = description.getAnnotation(WithUser.class); if (annotation == null) { annotation = description.getTestClass().getAnnotation(WithUser.class); } if (annotation != null) { - setSecurityContext(annotation); if (annotation.autoCreateTenant()) { - SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(annotation.tenantId()); + createTenant(annotation.tenantId()); } + setSecurityContext(annotation); } return oldContext; } - - /** - * @param annotation - */ + private void setSecurityContext(final WithUser annotation) { SecurityContextHolder.setContext(new SecurityContext() { - /** - * - */ private static final long serialVersionUID = 1L; @Override public void setAuthentication(final Authentication authentication) { + // nothing todo } @Override @@ -113,7 +104,8 @@ public class WithSpringAuthorityRule implements TestRule { if (addPermission) { allPermissions.add(permissionName); } - } catch (IllegalArgumentException | IllegalAccessException e) { + // don't want to log this exceptions. + } catch (@SuppressWarnings("squid:S1166") IllegalArgumentException | IllegalAccessException e) { // nope } } @@ -129,18 +121,17 @@ public class WithSpringAuthorityRule implements TestRule { private void after(final SecurityContext oldContext) { SecurityContextHolder.setContext(oldContext); } - + /** * Clears the current security context. */ - public void clear() - { + public void clear() { SecurityContextHolder.clearContext(); } /** * @param callable - * @return + * @return the callable result * @throws Exception */ public T runAsPrivileged(final Callable callable) throws Exception { @@ -148,17 +139,17 @@ public class WithSpringAuthorityRule implements TestRule { } /** - * + * * @param withUser * @param callable - * @return + * @return callable result * @throws Exception */ public T runAs(final WithUser withUser, final Callable callable) throws Exception { final SecurityContext oldContext = SecurityContextHolder.getContext(); setSecurityContext(withUser); if (withUser.autoCreateTenant()) { - SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(withUser.tenantId()); + createTenant(withUser.tenantId()); } try { return callable.call(); @@ -167,10 +158,20 @@ public class WithSpringAuthorityRule implements TestRule { } } + private void createTenant(final String tenantId) { + final SecurityContext oldContext = SecurityContextHolder.getContext(); + setSecurityContext(privilegedUser()); + try { + SystemManagementHolder.getInstance().getSystemManagement().getTenantMetadata(tenantId); + } finally { + after(oldContext); + } + } + public static WithUser withUser(final String principal, final String... authorities) { return withUserAndTenant(principal, "default", true, true, authorities); } - + public static WithUser withUser(final String principal, final boolean allSpPermision, final String... authorities) { return withUserAndTenant(principal, "default", true, allSpPermision, authorities); } @@ -185,6 +186,15 @@ public class WithSpringAuthorityRule implements TestRule { public static WithUser withUserAndTenant(final String principal, final String tenant, final boolean autoCreateTenant, final boolean allSpPermission, final String... authorities) { + return createWithUser(principal, tenant, autoCreateTenant, allSpPermission, authorities); + } + + private static WithUser privilegedUser() { + return createWithUser("bumlux", "default", true, true, new String[] { "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE" }); + } + + private static WithUser createWithUser(final String principal, final String tenant, final boolean autoCreateTenant, + final boolean allSpPermission, final String... authorities) { return new WithUser() { @Override @@ -214,7 +224,7 @@ public class WithSpringAuthorityRule implements TestRule { @Override public String[] removeFromAllPermission() { - return null; + return new String[0]; } @Override @@ -222,65 +232,10 @@ public class WithSpringAuthorityRule implements TestRule { return tenant; } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.WithUser#autoCreateTenant() - */ @Override public boolean autoCreateTenant() { return autoCreateTenant; } }; } - - private static WithUser privilegedUser() { - return new WithUser() { - - @Override - public Class annotationType() { - return WithUser.class; - } - - @Override - public String principal() { - return "bumlux"; - } - - @Override - public String credentials() { - return null; - } - - @Override - public String[] authorities() { - return new String[] { "ROLE_CONTROLLER" }; - } - - @Override - public boolean allSpPermissions() { - return true; - } - - @Override - public String[] removeFromAllPermission() { - return null; - } - - @Override - public String tenantId() { - return "default"; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.WithUser#autoCreateTenant() - */ - @Override - public boolean autoCreateTenant() { - return true; - } - }; - } } diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java index 3c5e0aee3..319ac9a38 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/MessageNotReadableException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.rest.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception which is thrown in case an request body is not well formaned and @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class MessageNotReadableException extends SpServerRtException { +public class MessageNotReadableException extends AbstractServerRtException { /** * diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java index 02a48ef78..81d70103b 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/ResponseExceptionHandler.java @@ -16,7 +16,7 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang3.exception.ExceptionUtils; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; import org.eclipse.hawkbit.repository.exception.MultiPartFileUploadException; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.slf4j.Logger; @@ -75,7 +75,7 @@ public class ResponseExceptionHandler { } /** - * method for handling exception of type SpServerRtException. Called by the + * method for handling exception of type AbstractServerRtException. Called by the * Spring-Framework for exception handling. * * @param request @@ -86,14 +86,14 @@ public class ResponseExceptionHandler { * @return the entity to be responded containing the exception information * as entity. */ - @ExceptionHandler(SpServerRtException.class) + @ExceptionHandler(AbstractServerRtException.class) public ResponseEntity handleSpServerRtExceptions(final HttpServletRequest request, final Exception ex) { logRequest(request, ex); final ExceptionInfo response = createExceptionInfo(ex); final HttpStatus responseStatus; - if (ex instanceof SpServerRtException) { - responseStatus = getStatusOrDefault(((SpServerRtException) ex).getError()); + if (ex instanceof AbstractServerRtException) { + responseStatus = getStatusOrDefault(((AbstractServerRtException) ex).getError()); } else { responseStatus = DEFAULT_RESPONSE_STATUS; } @@ -152,8 +152,8 @@ public class ResponseExceptionHandler { final ExceptionInfo response = new ExceptionInfo(); response.setMessage(ex.getMessage()); response.setExceptionClass(ex.getClass().getName()); - if (ex instanceof SpServerRtException) { - response.setErrorCode(((SpServerRtException) ex).getError().getKey()); + if (ex instanceof AbstractServerRtException) { + response.setErrorCode(((AbstractServerRtException) ex).getError().getKey()); } return response; diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java index a8d476ac1..d43cec066 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterSyntaxErrorException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.rest.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception used by the REST API in case of invalid sort parameter syntax. @@ -18,7 +18,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class SortParameterSyntaxErrorException extends SpServerRtException { +public class SortParameterSyntaxErrorException extends AbstractServerRtException { /** * diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java index b44b94917..6a79e8abe 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedDirectionException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.rest.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception used by the REST API in case of invalid sort parameter direction @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class SortParameterUnsupportedDirectionException extends SpServerRtException { +public class SortParameterUnsupportedDirectionException extends AbstractServerRtException { /** * diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java index c9ce0dcdd..a00d245ab 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/exception/SortParameterUnsupportedFieldException.java @@ -9,7 +9,7 @@ package org.eclipse.hawkbit.rest.exception; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Exception used by the REST API in case of invalid field name in the sort @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.exception.SpServerRtException; * * */ -public class SortParameterUnsupportedFieldException extends SpServerRtException { +public class SortParameterUnsupportedFieldException extends AbstractServerRtException { /** * diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/ByteRange.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/ByteRange.java index 667fc197d..0811ac312 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/ByteRange.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/ByteRange.java @@ -69,13 +69,10 @@ public class ByteRange { return total; } - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ @Override - public int hashCode() { // NOSONAR - as this is generated + // NOSONAR - as this is generated + @SuppressWarnings("squid:S864") + public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (end ^ end >>> 32); @@ -85,11 +82,6 @@ public class ByteRange { return result; } - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ @Override public boolean equals(final Object obj) { // NOSONAR - as this is generated if (this == obj) { diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileSteamingFailedException.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileSteamingFailedException.java index abf7c0245..472c78c2a 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileSteamingFailedException.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/util/FileSteamingFailedException.java @@ -9,12 +9,12 @@ package org.eclipse.hawkbit.rest.util; import org.eclipse.hawkbit.exception.SpServerError; -import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.exception.AbstractServerRtException; /** * Thrown if artifact content streaming to client failed. */ -public final class FileSteamingFailedException extends SpServerRtException { +public final class FileSteamingFailedException extends AbstractServerRtException { private static final long serialVersionUID = 1L; diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java index daf5f0dd9..866ee16bc 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/SpPermission.java @@ -185,18 +185,22 @@ public final class SpPermission { field.setAccessible(true); try { final String role = (String) field.get(null); - if (!(exclusionRoles.contains(role))) { - allPermissions.add(role); - } + addIfNotExcluded(exclusionRoles, allPermissions, role); } catch (final IllegalAccessException e) { LOGGER.error(e.getMessage(), e); } - } } return allPermissions; } + private static void addIfNotExcluded(final Collection exclusionRoles, final List allPermissions, + final String role) { + if (!(exclusionRoles.contains(role))) { + allPermissions.add(role); + } + } + /** * Contains all the spring security evaluation expressions for the * {@link PreAuthorize} annotation for method security. @@ -290,6 +294,14 @@ public final class SpPermission { public static final String HAS_AUTH_READ_TARGET = HAS_AUTH_PREFIX + READ_TARGET + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE; + /** + * Spring security eval hasAuthority expression to check if spring + * context contains {@link SpPermission#READ_TARGET_SEC_TOKEN} or + * {@link #IS_SYSTEM_CODE}. + */ + public static final String HAS_AUTH_READ_TARGET_SEC_TOKEN = HAS_AUTH_PREFIX + READ_TARGET_SEC_TOKEN + + HAS_AUTH_SUFFIX + HAS_AUTH_OR + IS_SYSTEM_CODE; + /** * Spring security eval hasAuthority expression to check if spring * context contains {@link SpPermission#CREATE_TARGET} or diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/UserAuthenticationFilter.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/UserAuthenticationFilter.java index ecd980b03..deaff089f 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/UserAuthenticationFilter.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/UserAuthenticationFilter.java @@ -51,7 +51,9 @@ public interface UserAuthenticationFilter { * @throws ServletException * servlet exception */ - + // this declaration of multiple checked exception is necessary so it's + // aligned with the servlet API. + @SuppressWarnings("squid:S1160") void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java index f2cfbbdbf..6e4ac7f8f 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityContextTenantAware.java @@ -28,11 +28,6 @@ import org.springframework.security.core.context.SecurityContextImpl; */ public class SecurityContextTenantAware implements TenantAware { - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.tenancy.TenantAware#getCurrentTenantId() - */ @Override public String getCurrentTenant() { final SecurityContext context = SecurityContextHolder.getContext(); @@ -56,7 +51,7 @@ public class SecurityContextTenantAware implements TenantAware { } } - private SecurityContext buildSecurityContext(final String tenant) { + private static SecurityContext buildSecurityContext(final String tenant) { final SecurityContextImpl securityContext = new SecurityContextImpl(); securityContext.setAuthentication( new AuthenticationDelegate(SecurityContextHolder.getContext().getAuthentication(), tenant)); @@ -68,7 +63,7 @@ public class SecurityContextTenantAware implements TenantAware { * {@link Authentication} object except setting the details specifically for * a specific tenant. */ - private class AuthenticationDelegate implements Authentication { + private static final class AuthenticationDelegate implements Authentication { private static final long serialVersionUID = 1L; private final Authentication delegate; diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java index da998c87c..4432fbb67 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java @@ -29,12 +29,12 @@ import org.springframework.stereotype.Service; import com.google.common.base.Throwables; /** - * + * A Service which provide to run system code. */ @Service public class SystemSecurityContext { - private static final Logger logger = LoggerFactory.getLogger(SystemSecurityContext.class); + private static final Logger LOG = LoggerFactory.getLogger(SystemSecurityContext.class); private final TenantAware tenantAware; @@ -96,19 +96,21 @@ public class SystemSecurityContext { public T runAsSystemAsTenant(final Callable callable, final String tenant) { final SecurityContext oldContext = SecurityContextHolder.getContext(); try { - logger.debug("entering system code execution"); + LOG.debug("entering system code execution"); return tenantAware.runAsTenant(tenant, () -> { try { setSystemContext(SecurityContextHolder.getContext()); return callable.call(); - } catch (final Exception e) { + // The callable API throws a Exception and not a specific + // one + } catch (@SuppressWarnings("squid:S2221") final Exception e) { throw Throwables.propagate(e); } }); } finally { SecurityContextHolder.setContext(oldContext); - logger.debug("leaving system code execution"); + LOG.debug("leaving system code execution"); } } @@ -134,7 +136,7 @@ public class SystemSecurityContext { * {@link SpringEvalExpressions#SYSTEM_ROLE} which is allowed to execute all * secured methods. */ - public static class SystemCodeAuthentication implements Authentication { + public static final class SystemCodeAuthentication implements Authentication { private static final long serialVersionUID = 1L; private static final List AUTHORITIES = Collections diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java index 4e4cb05a6..710d6d97c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java @@ -30,10 +30,7 @@ import com.vaadin.ui.VerticalLayout; * View class that is instantiated when no other view matches the navigation * state. * - * - * * @see Navigator#setErrorView(Class) - * */ @SuppressWarnings("serial") @SpringComponent diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java index cca4bdd4c..f064a76a1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitEventProvider.java @@ -12,25 +12,29 @@ import java.util.HashSet; import java.util.Set; 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.DistributionSetTagDeletedEvent; 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.RolloutGroupChangeEvent; 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.TargetTagCreatedBulkEvent; import org.eclipse.hawkbit.repository.eventbus.event.TargetTagDeletedEvent; import org.eclipse.hawkbit.repository.eventbus.event.TargetTagUpdateEvent; +import org.eclipse.hawkbit.repository.eventbus.event.TargetUpdatedEvent; /** * The default hawkbit event provider. */ public class HawkbitEventProvider implements UIEventProvider { - private static final Set> SINGLE_EVENTS = new HashSet<>(6); - private static final Set> BULK_EVENTS = new HashSet<>(3); + private static final Set> SINGLE_EVENTS = new HashSet<>(9); + private static final Set> BULK_EVENTS = new HashSet<>(5); static { SINGLE_EVENTS.add(TargetTagCreatedBulkEvent.class); @@ -41,10 +45,14 @@ public class HawkbitEventProvider implements UIEventProvider { SINGLE_EVENTS.add(RolloutGroupChangeEvent.class); SINGLE_EVENTS.add(RolloutChangeEvent.class); SINGLE_EVENTS.add(TargetTagUpdateEvent.class); + SINGLE_EVENTS.add(DistributionSetUpdateEvent.class); BULK_EVENTS.add(TargetCreatedEvent.class); BULK_EVENTS.add(TargetInfoUpdateEvent.class); BULK_EVENTS.add(TargetDeletedEvent.class); + BULK_EVENTS.add(DistributionDeletedEvent.class); + BULK_EVENTS.add(DistributionCreatedEvent.class); + BULK_EVENTS.add(TargetUpdatedEvent.class); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitUI.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitUI.java index f4c26a960..9768c2390 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitUI.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitUI.java @@ -14,7 +14,7 @@ import java.util.Set; import javax.servlet.http.Cookie; -import org.eclipse.hawkbit.ui.components.SPUIErrorHandler; +import org.eclipse.hawkbit.ui.components.HawkbitUIErrorHandler; import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent; import org.eclipse.hawkbit.ui.menu.DashboardMenu; import org.eclipse.hawkbit.ui.menu.DashboardMenuItem; @@ -50,13 +50,11 @@ import com.vaadin.ui.themes.ValoTheme; /** * Vaadin management UI. * - * - * - * */ -@SuppressWarnings("serial") @Title("hawkBit Update Server") public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { + private static final long serialVersionUID = 1L; + private static final Logger LOG = LoggerFactory.getLogger(HawkbitUI.class); private static final String EMPTY_VIEW = ""; @@ -139,7 +137,7 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { contentVerticalLayout.addComponent(content); content.setStyleName("view-content"); content.setSizeFull(); - rootLayout.setExpandRatio(contentVerticalLayout, 1.0f); + rootLayout.setExpandRatio(contentVerticalLayout, 1.0F); contentVerticalLayout.setStyleName("main-content"); contentVerticalLayout.setExpandRatio(content, 1.0F); setContent(rootLayout); @@ -154,6 +152,8 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { } final Navigator navigator = new Navigator(this, content); navigator.addViewChangeListener(new ViewChangeListener() { + private static final long serialVersionUID = 1L; + @Override public boolean beforeViewChange(final ViewChangeEvent event) { return true; @@ -180,7 +180,10 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { final String locale = getLocaleId(SPUIDefinitions.getAvailableLocales()); setLocale(new Locale(locale)); - UI.getCurrent().setErrorHandler(new SPUIErrorHandler()); + if (UI.getCurrent().getErrorHandler() == null) { + UI.getCurrent().setErrorHandler(new HawkbitUIErrorHandler()); + } + LOG.info("Current locale of the application is : {}", i18n.getLocale()); } @@ -197,7 +200,7 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { * as set * @return String as preferred locale */ - private String getLocaleId(final Set availableLocalesInApp) { + private static String getLocaleId(final Set availableLocalesInApp) { final String[] localeChain = getLocaleChain(); String spLocale = SPUIDefinitions.DEFAULT_LOCALE; if (null != localeChain) { @@ -217,16 +220,18 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { * * @return String as locales */ - private String[] getLocaleChain() { + private static String[] getLocaleChain() { String[] localeChain = null; // Fetch all cookies from the request final Cookie[] cookies = VaadinService.getCurrentRequest().getCookies(); - if (cookies != null) { - for (final Cookie c : cookies) { - if (c.getName().equals(SPUIDefinitions.COOKIE_NAME) && !c.getValue().isEmpty()) { - localeChain = c.getValue().split("#"); - break; - } + if (cookies == null) { + return localeChain; + } + + for (final Cookie c : cookies) { + if (c.getName().equals(SPUIDefinitions.COOKIE_NAME) && !c.getValue().isEmpty()) { + localeChain = c.getValue().split("#"); + break; } } return localeChain; @@ -234,6 +239,8 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { private class ManagementViewProvider implements ViewProvider { + private static final long serialVersionUID = 1L; + @Override public String getViewName(final String viewAndParameters) { return viewProvider.getViewName(getStartView(viewAndParameters)); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java index b07aa0276..ffbb3b7bd 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java @@ -158,7 +158,7 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW detailAndUploadLayout.setComponentAlignment(dadw, Alignment.MIDDLE_CENTER); } - detailAndUploadLayout.setExpandRatio(artifactDetailsLayout, 1.0f); + detailAndUploadLayout.setExpandRatio(artifactDetailsLayout, 1.0F); detailAndUploadLayout.setSizeFull(); detailAndUploadLayout.addStyleName("group"); detailAndUploadLayout.setSpacing(true); @@ -177,9 +177,9 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW mainLayout.addComponent(detailAndUploadLayout, 2, 0); mainLayout.addComponent(deleteActionsLayout, 1, 1); mainLayout.addComponent(uplaodButtonsLayout, 2, 1); - mainLayout.setRowExpandRatio(0, 1.0f); - mainLayout.setColumnExpandRatio(1, 0.5f); - mainLayout.setColumnExpandRatio(2, 0.5f); + mainLayout.setRowExpandRatio(0, 1.0F); + mainLayout.setColumnExpandRatio(1, 0.5F); + mainLayout.setColumnExpandRatio(2, 0.5F); mainLayout.setComponentAlignment(deleteActionsLayout, Alignment.BOTTOM_CENTER); mainLayout.setComponentAlignment(uplaodButtonsLayout, Alignment.BOTTOM_CENTER); return mainLayout; @@ -201,8 +201,8 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW private void maximizeSwTable() { mainLayout.removeComponent(detailAndUploadLayout); removeOtherComponents(); - mainLayout.setColumnExpandRatio(1, 1f); - mainLayout.setColumnExpandRatio(2, 0f); + mainLayout.setColumnExpandRatio(1, 1F); + mainLayout.setColumnExpandRatio(2, 0F); } private void minimizeArtifactoryDetails() { @@ -219,15 +219,15 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW mainLayout.removeComponent(smTableLayout); detailAndUploadLayout.removeComponent(dadw); removeOtherComponents(); - mainLayout.setColumnExpandRatio(1, 0f); - mainLayout.setColumnExpandRatio(2, 1f); + mainLayout.setColumnExpandRatio(1, 0F); + mainLayout.setColumnExpandRatio(2, 1F); } private void addOtherComponents() { mainLayout.addComponent(deleteActionsLayout, 1, 1); mainLayout.addComponent(uplaodButtonsLayout, 2, 1); - mainLayout.setColumnExpandRatio(1, 0.5f); - mainLayout.setColumnExpandRatio(2, 0.5f); + mainLayout.setColumnExpandRatio(1, 0.5F); + mainLayout.setColumnExpandRatio(2, 0.5F); mainLayout.setComponentAlignment(deleteActionsLayout, Alignment.BOTTOM_CENTER); mainLayout.setComponentAlignment(uplaodButtonsLayout, Alignment.BOTTOM_CENTER); } @@ -240,6 +240,8 @@ public class UploadArtifactView extends VerticalLayout implements View, BrowserW private void hideDropHints() { UI.getCurrent().addClickListener(new ClickListener() { + private static final long serialVersionUID = 1L; + @Override public void click(final com.vaadin.event.MouseEvents.ClickEvent event) { eventBus.publish(this, DragEvent.HIDE_DROP_HINT); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java index 80e8a2f4f..4ba722284 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java @@ -28,11 +28,6 @@ import org.vaadin.addons.lazyquerycontainer.QueryDefinition; /** * Simple implementation of generics bean query which dynamically loads artifact * beans. - * - * - * - * - * */ public class ArtifactBeanQuery extends AbstractBeanQuery { private static final long serialVersionUID = -333786310371208962L; @@ -74,7 +69,7 @@ public class ArtifactBeanQuery extends AbstractBeanQuery { @Override protected LocalArtifact constructBean() { - return entityFactory.generateLocalArtifact(); + return getEntityFactory().generateLocalArtifact(); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java index 15904169d..bbab490ab 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleDetails.java @@ -53,42 +53,42 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta @Autowired private transient SoftwareManagement softwareManagement; - + @Autowired private SwMetadataPopupLayout swMetadataPopupLayout; - + @Autowired - private EntityFactory entityFactory; - + private transient EntityFactory entityFactory; + private SoftwareModuleMetadatadetailslayout swmMetadataTable; - + /** * softwareLayout Initialize the component. */ @Override protected void init() { swmMetadataTable = new SoftwareModuleMetadatadetailslayout(); - swmMetadataTable.init(getI18n(), getPermissionChecker(),softwareManagement,swMetadataPopupLayout,entityFactory); + swmMetadataTable.init(getI18n(), getPermissionChecker(), softwareManagement, swMetadataPopupLayout, + entityFactory); super.init(); } - + @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final MetadataEvent event) { - UI.getCurrent() - .access(() -> { - SoftwareModuleMetadata softwareModuleMetadata = event.getSoftwareModuleMetadata(); - if (softwareModuleMetadata != null - && isSoftwareModuleSelected(softwareModuleMetadata.getSoftwareModule())) { - if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA) { - swmMetadataTable.createMetadata(event.getSoftwareModuleMetadata().getKey()); - } else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA) { - swmMetadataTable.deleteMetadata(event.getSoftwareModuleMetadata().getKey()); - } - } - }); + UI.getCurrent().access(() -> { + final SoftwareModuleMetadata softwareModuleMetadata = event.getSoftwareModuleMetadata(); + if (softwareModuleMetadata != null + && isSoftwareModuleSelected(softwareModuleMetadata.getSoftwareModule())) { + if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA) { + swmMetadataTable.createMetadata(event.getSoftwareModuleMetadata().getKey()); + } else if (event + .getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA) { + swmMetadataTable.deleteMetadata(event.getSoftwareModuleMetadata().getKey()); + } + } + }); } - - + @Override protected String getEditButtonId() { return SPUIComponentIdProvider.UPLOAD_SW_MODULE_EDIT_BUTTON; @@ -101,7 +101,7 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null); detailsTab.addTab(swmMetadataTable, getI18n().get("caption.metadata"), null); } - + @Override protected void onEdit(final ClickEvent event) { final Window addSoftwareModule = softwareModuleAddUpdateWindow @@ -115,10 +115,10 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta protected void populateDetailsWidget() { String maxAssign = HawkbitCommonUtil.SP_STRING_EMPTY; if (getSelectedBaseEntity() != null) { - if (getSelectedBaseEntity().getType().getMaxAssignments() == Integer.MAX_VALUE) { - maxAssign = getI18n().get("label.multiAssign.type"); - } else { + if (getSelectedBaseEntity().getType().getMaxAssignments() == 1) { maxAssign = getI18n().get("label.singleAssign.type"); + } else { + maxAssign = getI18n().get("label.multiAssign.type"); } updateSoftwareModuleDetailsLayout(getSelectedBaseEntity().getType().getName(), getSelectedBaseEntity().getVendor(), maxAssign); @@ -126,7 +126,7 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta updateSoftwareModuleDetailsLayout(HawkbitCommonUtil.SP_STRING_EMPTY, HawkbitCommonUtil.SP_STRING_EMPTY, maxAssign); } - + populateMetadataDetails(); } @@ -188,38 +188,30 @@ public class SoftwareModuleDetails extends AbstractNamedVersionedEntityTableDeta protected String getDetailsHeaderCaptionId() { return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID; } - - + @Override - protected void populateMetadataDetails(){ + protected void populateMetadataDetails() { swmMetadataTable.populateSMMetadata(getSelectedBaseEntity()); - } - - private boolean isSoftwareModuleSelected(SoftwareModule softwareModule) { - final SoftwareModule selectedUploadSWModule = artifactUploadState.getSelectedBaseSoftwareModule().isPresent() ? artifactUploadState - .getSelectedBaseSoftwareModule().get() : null; + } + + private boolean isSoftwareModuleSelected(final SoftwareModule softwareModule) { + final SoftwareModule selectedUploadSWModule = artifactUploadState.getSelectedBaseSoftwareModule().isPresent() + ? artifactUploadState.getSelectedBaseSoftwareModule().get() : null; return softwareModule != null && selectedUploadSWModule != null && selectedUploadSWModule.getName().equals(softwareModule.getName()) && selectedUploadSWModule.getVersion().equals(softwareModule.getVersion()); } - + @Override protected Boolean isMetadataIconToBeDisplayed() { return true; } - - @Override - protected String getShowMetadataButtonId() { - SoftwareModule selectedBaseEntity = getSelectedBaseEntity(); - return SPUIComponentIdProvider.SW_TABLE_MANAGE_METADATA_ID + "." + selectedBaseEntity.getName() + "." - + selectedBaseEntity.getVersion(); - } @Override - protected void showMetadata(ClickEvent event) { - SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(getSelectedBaseEntityId()); - /* display the window */ - UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule,null)); + protected void showMetadata(final ClickEvent event) { + final SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(getSelectedBaseEntityId()); + /* display the window */ + UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, null)); } - + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java index 6c5ef6159..06fb8ed18 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/CreateUpdateSoftwareTypeLayout.java @@ -185,6 +185,7 @@ public class CreateUpdateSoftwareTypeLayout extends CreateUpdateTypeLayout { assignOptiongroup.setStyleName(ValoTheme.OPTIONGROUP_SMALL); assignOptiongroup.addStyleName("custom-option-group"); assignOptiongroup.setNullSelectionAllowed(false); + assignOptiongroup.setId(SPUIDefinitions.ASSIGN_OPTION_GROUP_SOFTWARE_MODULE_TYPE_ID); assignOptiongroup.select(tagOptions.get(0)); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/SMTypeFilterButtons.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/SMTypeFilterButtons.java index d627a6dd0..88a9fa779 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/SMTypeFilterButtons.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtype/SMTypeFilterButtons.java @@ -8,7 +8,10 @@ */ package org.eclipse.hawkbit.ui.artifacts.smtype; +import java.util.EnumSet; + import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent; +import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleTypeEvent.SoftwareModuleTypeEnum; import org.eclipse.hawkbit.ui.artifacts.event.UploadArtifactUIEvent; import org.eclipse.hawkbit.ui.artifacts.event.UploadViewAcceptCriteria; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; @@ -46,12 +49,11 @@ public class SMTypeFilterButtons extends AbstractFilterButtons { @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final SoftwareModuleTypeEvent event) { - if (event.getSoftwareModuleTypeEnum() == SoftwareModuleTypeEvent.SoftwareModuleTypeEnum.ADD_SOFTWARE_MODULE_TYPE - || event.getSoftwareModuleTypeEnum() == SoftwareModuleTypeEvent.SoftwareModuleTypeEnum.UPDATE_SOFTWARE_MODULE_TYPE - || event.getSoftwareModuleTypeEnum() == SoftwareModuleTypeEvent.SoftwareModuleTypeEnum.DELETE_SOFTWARE_MODULE_TYPE - && event.getSoftwareModuleType() != null) { + if (event.getSoftwareModuleType() != null + && EnumSet.allOf(SoftwareModuleTypeEnum.class).contains(event.getSoftwareModuleTypeEnum())) { refreshTable(); } + } @EventBusListenerMethod(scope = EventScope.SESSION) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadConfirmationwindow.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadConfirmationwindow.java index 8455dea69..915aee48a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadConfirmationwindow.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadConfirmationwindow.java @@ -108,7 +108,7 @@ public class UploadConfirmationwindow implements Button.ClickListener { private UploadResultWindow currentUploadResultWindow; - private int redErrorLabelCount = 0; + private int redErrorLabelCount; private final ArtifactUploadState artifactUploadState; @@ -353,11 +353,8 @@ public class UploadConfirmationwindow implements Button.ClickListener { * label * @return Boolean */ - private Boolean isWarningIcon(final Label icon) { - if (icon.isVisible() && !icon.getStyleName().contains(SPUIStyleDefinitions.ERROR_LABEL)) { - return true; - } - return false; + private static Boolean isWarningIcon(final Label icon) { + return !isErrorIcon(icon); } /** @@ -367,14 +364,11 @@ public class UploadConfirmationwindow implements Button.ClickListener { * label * @return Boolean */ - private Boolean isErrorIcon(final Label icon) { - if (icon.isVisible() && icon.getStyleName().contains(SPUIStyleDefinitions.ERROR_LABEL)) { - return true; - } - return false; + private static Boolean isErrorIcon(final Label icon) { + return icon.isVisible() && icon.getStyleName().contains(SPUIStyleDefinitions.ERROR_LABEL); } - private Label getWarningLabel() { + private static Label getWarningLabel() { final Label warningIconLabel = new Label(); warningIconLabel.addStyleName(ValoTheme.LABEL_SMALL); warningIconLabel.setHeightUndefined(); @@ -436,7 +430,7 @@ public class UploadConfirmationwindow implements Button.ClickListener { private void hideErrorIcon(final Label warningLabel, final int errorLabelCount, final int duplicateCount, final Label errorLabel, final String oldFileName, final Long currentSwId) { - if (warningLabel == null && (errorLabelCount > 1 || duplicateCount == 1 && errorLabelCount == 1)) { + if (warningLabel == null && (errorLabelCount > 1 || (duplicateCount == 1 && errorLabelCount == 1))) { final ArtifactManagement artifactManagement = SpringContextHelper.getBean(ArtifactManagement.class); final List artifactList = artifactManagement.findByFilenameAndSoftwareModule(oldFileName, currentSwId); @@ -486,12 +480,12 @@ public class UploadConfirmationwindow implements Button.ClickListener { uploadDetailsTable.setColumnHeader(SIZE, i18n.get("upload.size")); uploadDetailsTable.setColumnHeader(ACTION, i18n.get("upload.action")); - uploadDetailsTable.setColumnExpandRatio(FILE_NAME_LAYOUT, 0.25f); - uploadDetailsTable.setColumnExpandRatio(SW_MODULE_NAME, 0.17f); - uploadDetailsTable.setColumnExpandRatio(SHA1_CHECKSUM, 0.2f); - uploadDetailsTable.setColumnExpandRatio(MD5_CHECKSUM, 0.2f); - uploadDetailsTable.setColumnExpandRatio(SIZE, 0.12f); - uploadDetailsTable.setColumnExpandRatio(ACTION, 0.06f); + uploadDetailsTable.setColumnExpandRatio(FILE_NAME_LAYOUT, 0.25F); + uploadDetailsTable.setColumnExpandRatio(SW_MODULE_NAME, 0.17F); + uploadDetailsTable.setColumnExpandRatio(SHA1_CHECKSUM, 0.2F); + uploadDetailsTable.setColumnExpandRatio(MD5_CHECKSUM, 0.2F); + uploadDetailsTable.setColumnExpandRatio(SIZE, 0.12F); + uploadDetailsTable.setColumnExpandRatio(ACTION, 0.06F); final Object[] visibileColumn = { FILE_NAME_LAYOUT, SW_MODULE_NAME, SHA1_CHECKSUM, MD5_CHECKSUM, SIZE, ACTION }; uploadDetailsTable.setVisibleColumns(visibileColumn); @@ -548,9 +542,7 @@ public class UploadConfirmationwindow implements Button.ClickListener { uploadConfrimationWindow.close(); } else if (event.getComponent().getId().equals(SPUIComponentIdProvider.UPLOAD_BUTTON)) { processArtifactUpload(); - } - - else if (event.getComponent().getId().startsWith(SPUIComponentIdProvider.UPLOAD_DELETE_ICON)) { + } else if (event.getComponent().getId().startsWith(SPUIComponentIdProvider.UPLOAD_DELETE_ICON)) { final String itemId = ((Button) event.getComponent()).getData().toString(); final Item item = uploadDetailsTable.getItem(((Button) event.getComponent()).getData()); final Long swId = (Long) item.getItemProperty(BASE_SOFTWARE_ID).getValue(); @@ -667,7 +659,7 @@ public class UploadConfirmationwindow implements Button.ClickListener { } - private void closeFileStream(final FileInputStream fis, final File newFile) { + private static void closeFileStream(final FileInputStream fis, final File newFile) { if (fis != null) { try { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java index af02e917b..71b041c9e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/upload/UploadLayout.java @@ -76,6 +76,11 @@ import com.vaadin.ui.VerticalLayout; @SpringComponent public class UploadLayout extends VerticalLayout { + /** + * + */ + private static final String HTML_DIV = ""; + private static final long serialVersionUID = -566164756606779220L; private static final Logger LOG = LoggerFactory.getLogger(UploadLayout.class); @@ -248,7 +253,7 @@ public class UploadLayout extends VerticalLayout { final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles(); // selected software module at the time of file drop is // considered for upload - SoftwareModule selectedSw = artifactUploadState.getSelectedBaseSoftwareModule().get(); + final SoftwareModule selectedSw = artifactUploadState.getSelectedBaseSoftwareModule().get(); // reset the flag hasDirectory = Boolean.FALSE; for (final Html5File file : files) { @@ -265,7 +270,7 @@ public class UploadLayout extends VerticalLayout { } } - private void processFile(final Html5File file, SoftwareModule selectedSw) { + private void processFile(final Html5File file, final SoftwareModule selectedSw) { if (!isDirectory(file)) { if (!checkForDuplicate(file.getFileName(), selectedSw)) { artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet(); @@ -276,7 +281,7 @@ public class UploadLayout extends VerticalLayout { } } - private StreamVariable createStreamVariable(final Html5File file, SoftwareModule selectedSw) { + private StreamVariable createStreamVariable(final Html5File file, final SoftwareModule selectedSw) { return new UploadHandler(file.getFileName(), file.getFileSize(), UploadLayout.this, spInfo.getMaxArtifactFileSize(), null, file.getType(), selectedSw); } @@ -366,11 +371,13 @@ public class UploadLayout extends VerticalLayout { * in case of upload errors */ OutputStream saveUploadedFileDetails(final String name, final long size, final String mimeType, - SoftwareModule selectedSw) { + final SoftwareModule selectedSw) { File tempFile = null; try { tempFile = File.createTempFile("spUiArtifactUpload", null); + // we return the outputstream so we cannot close it here + @SuppressWarnings("squid:S2095") final OutputStream out = new FileOutputStream(tempFile); final String currentBaseSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion(selectedSw.getName(), @@ -406,18 +413,12 @@ public class UploadLayout extends VerticalLayout { return checkIfSoftwareModuleIsSelected(); } - private boolean isFilesDropped(final DragAndDropEvent event) { + private static boolean isFilesDropped(final DragAndDropEvent event) { if (event.getTransferable() instanceof WrapperTransferable) { final Html5File[] files = ((WrapperTransferable) event.getTransferable()).getFiles(); - // other components can also be wrapped in WrapperTransferable , so - // additional check on files - if (files == null) { - return false; - } - return true; - } else { - return false; + return files != null; } + return false; } Boolean checkIfSoftwareModuleIsSelected() { @@ -441,12 +442,14 @@ public class UploadLayout extends VerticalLayout { * * @param name * file name + * @param selectedSoftwareModule + * the current selected sm module * @return Boolean */ public Boolean checkIfFileIsDuplicate(final String name, final SoftwareModule selectedSoftwareModule) { Boolean isDuplicate = false; - final String currentBaseSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( - selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); + final String currentBaseSoftwareModuleKey = HawkbitCommonUtil + .getFormattedNameVersion(selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); for (final CustomFile customFile : artifactUploadState.getFileSelected()) { final String fileSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( @@ -473,7 +476,7 @@ public class UploadLayout extends VerticalLayout { void updateActionCount() { if (!artifactUploadState.getFileSelected().isEmpty()) { processBtn.setCaption(SPUILabelDefinitions.PROCESS + "
" - + artifactUploadState.getFileSelected().size() + "
"); + + artifactUploadState.getFileSelected().size() + HTML_DIV); } else { processBtn.setCaption(SPUILabelDefinitions.PROCESS); } @@ -502,6 +505,9 @@ public class UploadLayout extends VerticalLayout { return message.toString(); } + /** + * Show the duplicated message. + */ public void showDuplicateMessage() { uiNotification.displayValidationError(getDuplicateFileValidationMessage()); } @@ -510,9 +516,9 @@ public class UploadLayout extends VerticalLayout { artifactUploadState.getNumberOfFileUploadsExpected().incrementAndGet(); } - void updateFileSize(final String name, final long size, SoftwareModule selectedSoftwareModule) { - final String currentBaseSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( - selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); + void updateFileSize(final String name, final long size, final SoftwareModule selectedSoftwareModule) { + final String currentBaseSoftwareModuleKey = HawkbitCommonUtil + .getFormattedNameVersion(selectedSoftwareModule.getName(), selectedSoftwareModule.getVersion()); for (final CustomFile customFile : artifactUploadState.getFileSelected()) { final String fileSoftwareModuleKey = HawkbitCommonUtil.getFormattedNameVersion( @@ -594,12 +600,12 @@ public class UploadLayout extends VerticalLayout { private void setConfirmationPopupHeightWidth(final float newWidth, final float newHeight) { if (currentUploadConfirmationwindow != null) { - currentUploadConfirmationwindow.getUploadArtifactDetails().setWidth( - HawkbitCommonUtil.getArtifactUploadPopupWidth(newWidth, - SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), Unit.PIXELS); - currentUploadConfirmationwindow.getUploadDetailsTable().setHeight( - HawkbitCommonUtil.getArtifactUploadPopupHeight(newHeight, - SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), Unit.PIXELS); + currentUploadConfirmationwindow.getUploadArtifactDetails().setWidth(HawkbitCommonUtil + .getArtifactUploadPopupWidth(newWidth, SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), + Unit.PIXELS); + currentUploadConfirmationwindow.getUploadDetailsTable().setHeight(HawkbitCommonUtil + .getArtifactUploadPopupHeight(newHeight, SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), + Unit.PIXELS); } } @@ -616,12 +622,10 @@ public class UploadLayout extends VerticalLayout { && currentUploadConfirmationwindow.getCurrentUploadResultWindow() != null) { final UploadResultWindow uploadResultWindow = currentUploadConfirmationwindow .getCurrentUploadResultWindow(); - uploadResultWindow.getUploadResultsWindow().setWidth( - HawkbitCommonUtil.getArtifactUploadPopupWidth(newWidth, - SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), Unit.PIXELS); - uploadResultWindow.getUploadResultTable().setHeight( - HawkbitCommonUtil.getArtifactUploadPopupHeight(newHeight, - SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), Unit.PIXELS); + uploadResultWindow.getUploadResultsWindow().setWidth(HawkbitCommonUtil.getArtifactUploadPopupWidth(newWidth, + SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_WIDTH), Unit.PIXELS); + uploadResultWindow.getUploadResultTable().setHeight(HawkbitCommonUtil.getArtifactUploadPopupHeight( + newHeight, SPUIDefinitions.MIN_UPLOAD_CONFIRMATION_POPUP_HEIGHT), Unit.PIXELS); } } @@ -632,8 +636,8 @@ public class UploadLayout extends VerticalLayout { } else { currentUploadConfirmationwindow = new UploadConfirmationwindow(this, artifactUploadState); UI.getCurrent().addWindow(currentUploadConfirmationwindow.getUploadConfrimationWindow()); - setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(), Page.getCurrent() - .getBrowserWindowHeight()); + setConfirmationPopupHeightWidth(Page.getCurrent().getBrowserWindowWidth(), + Page.getCurrent().getBrowserWindowHeight()); } } } @@ -682,7 +686,7 @@ public class UploadLayout extends VerticalLayout { displayDuplicateValidationMessage(); } - private void onUploadStreamingFailure(UploadStatusEvent event) { + private void onUploadStreamingFailure(final UploadStatusEvent event) { /** * If upload interrupted because of duplicate file,do not remove the * file already in upload list @@ -691,13 +695,13 @@ public class UploadLayout extends VerticalLayout { || !getDuplicateFileNamesList().contains(event.getUploadStatus().getFileName())) { final SoftwareModule sw = event.getUploadStatus().getSoftwareModule(); if (sw != null) { - getFileSelected().remove( - new CustomFile(event.getUploadStatus().getFileName(), sw.getName(), sw.getVersion())); + getFileSelected() + .remove(new CustomFile(event.getUploadStatus().getFileName(), sw.getName(), sw.getVersion())); } // failed reason to be updated only if there is error other than // duplicate file error - uploadInfoWindow.uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus() - .getFailureReason(), event.getUploadStatus().getSoftwareModule()); + uploadInfoWindow.uploadFailed(event.getUploadStatus().getFileName(), + event.getUploadStatus().getFailureReason(), event.getUploadStatus().getSoftwareModule()); increaseNumberOfFileUploadsFailed(); } decreaseNumberOfFileUploadsExpected(); @@ -711,9 +715,9 @@ public class UploadLayout extends VerticalLayout { displayDuplicateValidationMessage(); } - private void onUploadSuccess(UploadStatusEvent event) { - updateFileSize(event.getUploadStatus().getFileName(), event.getUploadStatus().getContentLength(), event - .getUploadStatus().getSoftwareModule()); + private void onUploadSuccess(final UploadStatusEvent event) { + updateFileSize(event.getUploadStatus().getFileName(), event.getUploadStatus().getContentLength(), + event.getUploadStatus().getSoftwareModule()); // recorded that we now one more uploaded increaseNumberOfFilesActuallyUpload(); } @@ -730,8 +734,8 @@ public class UploadLayout extends VerticalLayout { } private boolean isUploadComplete() { - int uploadedCount = artifactUploadState.getNumberOfFilesActuallyUpload().intValue(); - int expectedUploadsCount = artifactUploadState.getNumberOfFileUploadsExpected().intValue(); + final int uploadedCount = artifactUploadState.getNumberOfFilesActuallyUpload().intValue(); + final int expectedUploadsCount = artifactUploadState.getNumberOfFileUploadsExpected().intValue(); return uploadedCount == expectedUploadsCount; } @@ -744,13 +748,13 @@ public class UploadLayout extends VerticalLayout { || !getDuplicateFileNamesList().contains(event.getUploadStatus().getFileName())) { final SoftwareModule sw = event.getUploadStatus().getSoftwareModule(); if (sw != null) { - getFileSelected().remove( - new CustomFile(event.getUploadStatus().getFileName(), sw.getName(), sw.getVersion())); + getFileSelected() + .remove(new CustomFile(event.getUploadStatus().getFileName(), sw.getName(), sw.getVersion())); } // failed reason to be updated only if there is error other than // duplicate file error - uploadInfoWindow.uploadFailed(event.getUploadStatus().getFileName(), event.getUploadStatus() - .getFailureReason(), event.getUploadStatus().getSoftwareModule()); + uploadInfoWindow.uploadFailed(event.getUploadStatus().getFileName(), + event.getUploadStatus().getFailureReason(), event.getUploadStatus().getSoftwareModule()); increaseNumberOfFileUploadsFailed(); decreaseNumberOfFileUploadsExpected(); } @@ -773,8 +777,8 @@ public class UploadLayout extends VerticalLayout { * @param selectedBaseSoftwareModule */ public void refreshArtifactDetailsLayout(final SoftwareModule selectedBaseSoftwareModule) { - eventBus.publish(this, new SoftwareModuleEvent(SoftwareModuleEventType.ARTIFACTS_CHANGED, - selectedBaseSoftwareModule)); + eventBus.publish(this, + new SoftwareModuleEvent(SoftwareModuleEventType.ARTIFACTS_CHANGED, selectedBaseSoftwareModule)); } /** @@ -804,19 +808,19 @@ public class UploadLayout extends VerticalLayout { } void updateStatusButtonCount() { - int uploadsPending = artifactUploadState.getNumberOfFileUploadsExpected().get() + final int uploadsPending = artifactUploadState.getNumberOfFileUploadsExpected().get() - artifactUploadState.getNumberOfFilesActuallyUpload().get(); - int uploadsFailed = artifactUploadState.getNumberOfFileUploadsFailed().get(); - StringBuilder builder = new StringBuilder(""); + final int uploadsFailed = artifactUploadState.getNumberOfFileUploadsFailed().get(); + final StringBuilder builder = new StringBuilder(""); if (uploadsFailed != 0) { if (uploadsPending != 0) { - builder.append("
" + uploadsFailed + "
"); + builder.append("
" + uploadsFailed + HTML_DIV); } else { - builder.append("
" + uploadsFailed + "
"); + builder.append("
" + uploadsFailed + HTML_DIV); } } if (uploadsPending != 0) { - builder.append("
" + uploadsPending + "
"); + builder.append("
" + uploadsPending + HTML_DIV); } uploadStatusButton.setCaption(builder.toString()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerConstants.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerConstants.java index 06e280e4e..86a986e3a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerConstants.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerConstants.java @@ -14,7 +14,7 @@ import com.vaadin.shared.ui.colorpicker.Color; * Provides color constants for the ColorPickerLayout * */ -public class ColorPickerConstants { +public final class ColorPickerConstants { public static final String DEFAULT_COLOR = "rgb(44,151,32)"; public static final Color START_COLOR = new Color(0, 146, 58); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerHelper.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerHelper.java index 923c58fe3..1f80bf5ab 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerHelper.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/colorpicker/ColorPickerHelper.java @@ -20,7 +20,7 @@ import com.vaadin.ui.Slider.ValueOutOfBoundsException; * Contains helper methods for the ColorPickerLayout to handle the ColorPicker * */ -public class ColorPickerHelper { +public final class ColorPickerHelper { private static final Logger LOG = LoggerFactory.getLogger(ColorPickerHelper.class); @@ -30,7 +30,9 @@ public class ColorPickerHelper { /** * Get color picked value as string. - * + * + * @param preview + * the color picker preview * @return String of color picked value. */ public static String getColorPickedString(final SpColorPickerPreview preview) { @@ -59,7 +61,7 @@ public class ColorPickerHelper { final int green = Integer.parseInt(colors[1]); final int blue = Integer.parseInt(colors[2]); if (colors.length > 3) { - final int alpha = (int) (Double.parseDouble(colors[3]) * 255d); + final int alpha = (int) (Double.parseDouble(colors[3]) * 255D); return new Color(red, green, blue, alpha); } return new Color(red, green, blue); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/AbstractMetadataPopupLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/AbstractMetadataPopupLayout.java index 050d7c79f..ff1cc3db1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/AbstractMetadataPopupLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/AbstractMetadataPopupLayout.java @@ -38,7 +38,6 @@ import com.vaadin.server.FontAwesome; import com.vaadin.ui.AbstractTextField.TextChangeEventMode; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; -import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.CustomComponent; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.SelectionMode; @@ -98,7 +97,7 @@ public abstract class AbstractMetadataPopupLayout { if (ok) { - deleteMetadata(getSelectedEntity(), key, value); - uiNotification.displaySuccess(i18n.get("message.metadata.deleted.successfully", key)); - final Object selectedRow = metaDataGrid.getSelectedRow(); - metaDataGrid.getContainerDataSource().removeItem(event.getItemId()); - // force grid to refresh - metaDataGrid.clearSortOrder(); - if (!metaDataGrid.getContainerDataSource().getItemIds().isEmpty()) { - if (selectedRow != null) { - if (selectedRow.equals(event.getItemId())) { - metaDataGrid.select(metaDataGrid.getContainerDataSource().getIdByIndex(0)); - } else { - metaDataGrid.select(selectedRow); - } - } - } else { - keyTextField.clear(); - valueTextArea.clear(); - metaDataGrid.select(null); - if (hasCreatePermission()) { - keyTextField.setEnabled(true); - valueTextArea.setEnabled(true); - addIcon.setEnabled(false); - } - } + handleOkDeleteMetadata(event, key, value); } }); UI.getCurrent().addWindow(confirmDialog.getWindow()); confirmDialog.getWindow().bringToFront(); } + private void handleOkDeleteMetadata(final RendererClickEvent event, final String key, final String value) { + deleteMetadata(getSelectedEntity(), key, value); + uiNotification.displaySuccess(i18n.get("message.metadata.deleted.successfully", key)); + final Object selectedRow = metaDataGrid.getSelectedRow(); + metaDataGrid.getContainerDataSource().removeItem(event.getItemId()); + // force grid to refresh + metaDataGrid.clearSortOrder(); + if (!metaDataGrid.getContainerDataSource().getItemIds().isEmpty()) { + if (selectedRow != null) { + if (selectedRow.equals(event.getItemId())) { + metaDataGrid.select(metaDataGrid.getContainerDataSource().getIdByIndex(0)); + } else { + metaDataGrid.select(selectedRow); + } + } + } else { + clearTextFields(); + } + } + + private void clearTextFields() { + keyTextField.clear(); + valueTextArea.clear(); + metaDataGrid.select(null); + if (hasCreatePermission()) { + keyTextField.setEnabled(true); + valueTextArea.setEnabled(true); + addIcon.setEnabled(false); + } + } + private Button createAddIcon() { addIcon = SPUIComponentProvider.getButton(SPUIComponentIdProvider.METADTA_ADD_ICON_ID, i18n.get("button.save"), null, null, false, FontAwesome.PLUS, SPUIButtonStyleSmallNoBorder.class); - addIcon.addClickListener(event -> onAdd(event)); + addIcon.addClickListener(event -> onAdd()); return addIcon; } private Label createHeaderCaption() { - final Label captionLabel = SPUIComponentProvider.getLabel(i18n.get("caption.metadata"), - SPUILabelDefinitions.SP_WIDGET_CAPTION); - return captionLabel; + return SPUIComponentProvider.getLabel(i18n.get("caption.metadata"), SPUILabelDefinitions.SP_WIDGET_CAPTION); } - private IndexedContainer getMetadataContainer() { + private static IndexedContainer getMetadataContainer() { final IndexedContainer swcontactContainer = new IndexedContainer(); swcontactContainer.addContainerProperty(KEY, String.class, ""); swcontactContainer.addContainerProperty(VALUE, String.class, ""); @@ -340,7 +344,7 @@ public abstract class AbstractMetadataPopupLayout close(); + private final ClickListener closeClickListener = event -> close(); private final transient Map orginalValues; @@ -115,6 +115,10 @@ public class CommonDialogWindow extends Window implements Serializable { * the saveButtonClickListener * @param cancelButtonClickListener * the cancelButtonClickListener + * @param layout + * the abstract layout + * @param i18n + * the i18n service */ public CommonDialogWindow(final String caption, final Component content, final String helpLink, final ClickListener saveButtonClickListener, final ClickListener cancelButtonClickListener, @@ -233,11 +237,11 @@ public class CommonDialogWindow extends Window implements Serializable { } protected void addCloseListenerForSaveButton() { - saveButton.addClickListener(close); + saveButton.addClickListener(closeClickListener); } protected void addCloseListenerForCancelButton() { - cancelButton.addClickListener(close); + cancelButton.addClickListener(closeClickListener); } protected void addComponenetListeners() { @@ -275,7 +279,8 @@ public class CommonDialogWindow extends Window implements Serializable { return false; } - private boolean isValueEquals(final AbstractField field, final Object orginalValue, final Object currentValue) { + private static boolean isValueEquals(final AbstractField field, final Object orginalValue, + final Object currentValue) { if (Set.class.equals(field.getType())) { return CollectionUtils.isEqualCollection(CollectionUtils.emptyIfNull((Collection) orginalValue), CollectionUtils.emptyIfNull((Collection) currentValue)); @@ -289,7 +294,7 @@ public class CommonDialogWindow extends Window implements Serializable { return Objects.equals(orginalValue, currentValue); } - private Object getCurrentVaue(final Component currentChangedComponent, final Object newValue, + private static Object getCurrentVaue(final Component currentChangedComponent, final Object newValue, final AbstractField field) { Object currentValue = field.getValue(); if (field instanceof Table) { @@ -365,7 +370,7 @@ public class CommonDialogWindow extends Window implements Serializable { return false; } - private List> getAllComponents(final AbstractLayout abstractLayout) { + private static List> getAllComponents(final AbstractLayout abstractLayout) { final List> components = new ArrayList<>(); final Iterator iterate = abstractLayout.iterator(); @@ -464,6 +469,7 @@ public class CommonDialogWindow extends Window implements Serializable { private class ChangeListener implements ValueChangeListener, TextChangeListener, ItemSetChangeListener { + private static final long serialVersionUID = 1L; private final Field field; public ChangeListener(final Field field) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java index b6475f647..df6483592 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/AbstractTableDetailsLayout.java @@ -64,7 +64,7 @@ public abstract class AbstractTableDetailsLayout extends private Button editButton; private Button manageMetadataBtn; - + private TabSheet detailsTab; private VerticalLayout detailsLayout; @@ -140,11 +140,11 @@ public abstract class AbstractTableDetailsLayout extends editButton.addClickListener(this::onEdit); editButton.setEnabled(false); - manageMetadataBtn = SPUIComponentProvider.getButton("", "", "", null, false, - FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class); + manageMetadataBtn = SPUIComponentProvider.getButton("", "", "", null, false, FontAwesome.LIST_ALT, + SPUIButtonStyleSmallNoBorder.class); manageMetadataBtn.setId(getEditButtonId()); manageMetadataBtn.setDescription(i18n.get("tooltip.metadata.icon")); - manageMetadataBtn.addClickListener(this::showMetadata); + manageMetadataBtn.addClickListener(this::showMetadata); manageMetadataBtn.setEnabled(false); detailsTab = SPUIComponentProvider.getDetailsTabSheet(); @@ -222,7 +222,6 @@ public abstract class AbstractTableDetailsLayout extends populateLog(); populateDescription(); populateDetailsWidget(); - populateMetadataDetails(); } protected void populateLog() { @@ -295,8 +294,8 @@ public abstract class AbstractTableDetailsLayout extends descriptionLayout = getTabLayout(); return descriptionLayout; } - - /** + + /** * Default caption of header to be displayed when no data row selected in * table. * @@ -341,7 +340,7 @@ public abstract class AbstractTableDetailsLayout extends } protected abstract void populateDetailsWidget(); - + protected abstract void populateMetadataDetails(); protected Long getSelectedBaseEntityId() { @@ -352,10 +351,8 @@ public abstract class AbstractTableDetailsLayout extends protected abstract String getName(); - protected abstract String getShowMetadataButtonId(); - protected abstract Boolean isMetadataIconToBeDisplayed(); - + protected abstract void showMetadata(Button.ClickEvent event); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java index d3892a9dc..6a2c0401f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/DistributionSetMetadatadetailslayout.java @@ -40,38 +40,37 @@ import com.vaadin.ui.themes.ValoTheme; @SpringComponent @VaadinSessionScope -public class DistributionSetMetadatadetailslayout extends Table{ - +public class DistributionSetMetadatadetailslayout extends Table { + private static final long serialVersionUID = 2913758299611837718L; - - - private DistributionSetManagement distributionSetManagement; - + + private DistributionSetManagement distributionSetManagement; + private DsMetadataPopupLayout dsMetadataPopupLayout; private static final String METADATA_KEY = "Key"; - - private static final String VIEW ="view"; + + private static final String VIEW = "view"; private SpPermissionChecker permissionChecker; - + private transient EntityFactory entityFactory; private I18N i18n; - - private Long selectedDistSetId; - - /** - * - * @param i18n - * @param permissionChecker - * @param distributionSetManagement - * @param dsMetadataPopupLayout - */ + + private Long selectedDistSetId; + + /** + * Initialize the component. + * @param i18n + * @param permissionChecker + * @param distributionSetManagement + * @param dsMetadataPopupLayout + * @param entityFactory + */ public void init(final I18N i18n, final SpPermissionChecker permissionChecker, - final DistributionSetManagement distributionSetManagement, - final DsMetadataPopupLayout dsMetadataPopupLayout, - final EntityFactory entityFactory) { + final DistributionSetManagement distributionSetManagement, + final DsMetadataPopupLayout dsMetadataPopupLayout, final EntityFactory entityFactory) { this.i18n = i18n; this.permissionChecker = permissionChecker; this.distributionSetManagement = distributionSetManagement; @@ -80,7 +79,6 @@ public class DistributionSetMetadatadetailslayout extends Table{ createDSMetadataTable(); addCustomGeneratedColumns(); } - /** * Populate software module metadata. @@ -90,35 +88,15 @@ public class DistributionSetMetadatadetailslayout extends Table{ public void populateDSMetadata(final DistributionSet distributionSet) { removeAllItems(); if (null == distributionSet) { - return; + return; } selectedDistSetId = distributionSet.getId(); - final List dsMetadataList = distributionSet.getMetadata(); + final List dsMetadataList = distributionSetManagement + .findDistributionSetMetadataByDistributionSetId(selectedDistSetId); if (null != dsMetadataList && !dsMetadataList.isEmpty()) { 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() { @@ -131,9 +109,9 @@ public class DistributionSetMetadatadetailslayout extends Table{ setContainerDataSource(getDistSetContainer()); setColumnHeaderMode(ColumnHeaderMode.EXPLICIT); addDSMetadataTableHeader(); - setSizeFull(); - //same as height of other tabs in details tabsheet - setHeight(116,Unit.PIXELS); + setSizeFull(); + // same as height of other tabs in details tabsheet + setHeight(116, Unit.PIXELS); } private IndexedContainer getDistSetContainer() { @@ -141,7 +119,7 @@ public class DistributionSetMetadatadetailslayout extends Table{ container.addContainerProperty(METADATA_KEY, String.class, ""); setColumnExpandRatio(METADATA_KEY, 0.7f); setColumnAlignment(METADATA_KEY, Align.LEFT); - + if (permissionChecker.hasUpdateDistributionPermission()) { container.addContainerProperty(VIEW, Label.class, ""); setColumnExpandRatio(VIEW, 0.2F); @@ -154,39 +132,36 @@ public class DistributionSetMetadatadetailslayout extends Table{ 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()); item.getItemProperty(METADATA_KEY).setValue(dsMetadata.getKey()); - + } - - private void addCustomGeneratedColumns() { - addGeneratedColumn(METADATA_KEY, - (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); + + private void addCustomGeneratedColumns() { + addGeneratedColumn(METADATA_KEY, (source, itemId, columnId) -> customMetadataDetailButton((String) itemId)); } private Button customMetadataDetailButton(final String metadataKey) { - final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, "View " - + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); + final Button viewIcon = SPUIComponentProvider.getButton(getDetailLinkId(metadataKey), metadataKey, + "View " + metadataKey + " Metadata details", null, false, null, SPUIButtonStyleSmallNoBorder.class); viewIcon.setData(metadataKey); viewIcon.addStyleName(ValoTheme.BUTTON_TINY + " " + ValoTheme.BUTTON_LINK + " " + "on-focus-no-border link" + " " + "text-style"); viewIcon.addClickListener(event -> showMetadataDetails(selectedDistSetId, metadataKey)); return viewIcon; } - + private static String getDetailLinkId(final String name) { - return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name) - .toString(); + return new StringBuilder(SPUIComponentIdProvider.DS_METADATA_DETAIL_LINK).append('.').append(name).toString(); } - - private void showMetadataDetails(final Long selectedDistSetId , final String metadataKey) { - DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId); - + + private void showMetadataDetails(final Long selectedDistSetId, final String metadataKey) { + final DistributionSet distSet = distributionSetManagement.findDistributionSetById(selectedDistSetId); + /* display the window */ UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(distSet, - entityFactory.generateDistributionSetMetadata(distSet, metadataKey, "") )); + entityFactory.generateDistributionSetMetadata(distSet, metadataKey, ""))); } - + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java index 6e4c7dddd..a7adb8711 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleDetailsTable.java @@ -37,8 +37,10 @@ import com.vaadin.data.util.IndexedContainer; import com.vaadin.server.FontAwesome; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.ValoTheme; /** @@ -60,8 +62,6 @@ public class SoftwareModuleDetailsTable extends Table { private static final String SOFT_TYPE_MANDATORY = "mandatory"; - private static final String UNASSIGN_SOFT_MODULE = "unassignSoftModule"; - private boolean isTargetAssigned; private boolean isUnassignSoftModAllowed; @@ -109,7 +109,6 @@ public class SoftwareModuleDetailsTable extends Table { private void createSwModuleTable() { addStyleName(ValoTheme.TABLE_NO_HORIZONTAL_LINES); - addStyleName(ValoTheme.TABLE_NO_STRIPES); setSelectable(false); setImmediate(true); setContainerDataSource(getSwModuleContainer()); @@ -123,22 +122,13 @@ public class SoftwareModuleDetailsTable extends Table { final IndexedContainer container = new IndexedContainer(); container.addContainerProperty(SOFT_TYPE_MANDATORY, Label.class, ""); container.addContainerProperty(SOFT_TYPE_NAME, Label.class, ""); - container.addContainerProperty(SOFT_MODULE, Label.class, ""); - if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission()) { - container.addContainerProperty(UNASSIGN_SOFT_MODULE, Button.class, ""); - } + container.addContainerProperty(SOFT_MODULE, VerticalLayout.class, ""); setColumnExpandRatio(SOFT_TYPE_MANDATORY, 0.1f); setColumnExpandRatio(SOFT_TYPE_NAME, 0.4f); setColumnExpandRatio(SOFT_MODULE, 0.3f); - if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission()) { - setColumnExpandRatio(UNASSIGN_SOFT_MODULE, 0.2F); - } setColumnAlignment(SOFT_TYPE_MANDATORY, Align.RIGHT); setColumnAlignment(SOFT_TYPE_NAME, Align.LEFT); setColumnAlignment(SOFT_MODULE, Align.LEFT); - if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission()) { - setColumnAlignment(UNASSIGN_SOFT_MODULE, Align.RIGHT); - } return container; } @@ -146,10 +136,6 @@ public class SoftwareModuleDetailsTable extends Table { setColumnHeader(SOFT_TYPE_MANDATORY, ""); setColumnHeader(SOFT_TYPE_NAME, i18n.get("header.caption.typename")); setColumnHeader(SOFT_MODULE, i18n.get("header.caption.softwaremodule")); - if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission()) { - setColumnHeader(UNASSIGN_SOFT_MODULE, i18n.get("header.caption.unassign")); - } - } /** @@ -188,37 +174,29 @@ public class SoftwareModuleDetailsTable extends Table { final Item saveTblitem = getContainerDataSource().addItem(swModType.getName()); final Label mandatoryLabel = createMandatoryLabel(isMandatory); final Label typeName = HawkbitCommonUtil.getFormatedLabel(swModType.getName()); + final VerticalLayout verticalLayout = createSoftModuleLayout(swModType, distributionSet, + alreadyAssignedSwModules); - final Label softwareModule = HawkbitCommonUtil.getFormatedLabel(HawkbitCommonUtil.SP_STRING_EMPTY); - final Button reassignSoftModule = SPUIComponentProvider.getButton(swModType.getName(), "", "", "", true, - FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class); - - reassignSoftModule.addClickListener(event -> unassignSW(event, distributionSet, alreadyAssignedSwModules)); - if (null != alreadyAssignedSwModules && !alreadyAssignedSwModules.isEmpty()) { - final String swModuleName = getSwModuleName(alreadyAssignedSwModules, swModType); - softwareModule.setValue(swModuleName); - softwareModule.setDescription(swModuleName); - } saveTblitem.getItemProperty(SOFT_TYPE_MANDATORY).setValue(mandatoryLabel); saveTblitem.getItemProperty(SOFT_TYPE_NAME).setValue(typeName); - saveTblitem.getItemProperty(SOFT_MODULE).setValue(softwareModule); - if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission() && !isTargetAssigned - && (isSoftModAvaiableForSoftType(alreadyAssignedSwModules, swModType))) { - saveTblitem.getItemProperty(UNASSIGN_SOFT_MODULE).setValue(reassignSoftModule); - } + saveTblitem.getItemProperty(SOFT_MODULE).setValue(verticalLayout); } private void unassignSW(final ClickEvent event, final DistributionSet distributionSet, final Set alreadyAssignedSwModules) { - final SoftwareModule unAssignedSw = getSoftwareModule((Label) getContainerDataSource() - .getItem(event.getButton().getId()).getItemProperty(SOFT_MODULE).getValue(), alreadyAssignedSwModules); - final DistributionSet newDistributionSet = distributionSetManagement.unassignSoftwareModule(distributionSet, - unAssignedSw); - manageDistUIState.setLastSelectedEntity(DistributionSetIdName.generate(newDistributionSet)); - eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, newDistributionSet)); - eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION); - uiNotification.displaySuccess(i18n.get("message.sw.unassigned", unAssignedSw.getName())); + final SoftwareModule unAssignedSw = getSoftwareModule(event.getButton().getId(), alreadyAssignedSwModules); + if (distributionSetManagement.isDistributionSetInUse(distributionSet)) { + uiNotification.displayValidationError(i18n.get("message.error.notification.ds.target.assigned",distributionSet.getName(), distributionSet.getVersion())); + } else { + final DistributionSet newDistributionSet = distributionSetManagement.unassignSoftwareModule(distributionSet, + unAssignedSw); + manageDistUIState.setLastSelectedEntity(DistributionSetIdName.generate(newDistributionSet)); + eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.SELECTED_ENTITY, newDistributionSet)); + eventBus.publish(this, DistributionsUIEvent.ORDER_BY_DISTRIBUTION); + uiNotification.displaySuccess(i18n.get("message.sw.unassigned", unAssignedSw.getName())); + } + } private static boolean isSoftModAvaiableForSoftType(final Set swModulesSet, @@ -233,15 +211,46 @@ public class SoftwareModuleDetailsTable extends Table { } + private VerticalLayout createSoftModuleLayout(final SoftwareModuleType swModType, + final DistributionSet distributionSet, final Set alreadyAssignedSwModules) { + final VerticalLayout verticalLayout = new VerticalLayout(); + for (final SoftwareModule sw : alreadyAssignedSwModules) { + if (swModType.getKey().equals(sw.getType().getKey())) { + final HorizontalLayout horizontalLayout = new HorizontalLayout(); + horizontalLayout.setSizeFull(); + final Label softwareModule = HawkbitCommonUtil.getFormatedLabel(HawkbitCommonUtil.SP_STRING_EMPTY); + final Button reassignSoftModule = SPUIComponentProvider.getButton(sw.getName(), "", "", "", true, + FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class); + reassignSoftModule + .addClickListener(event -> unassignSW(event, distributionSet, alreadyAssignedSwModules)); + final String softwareModNameVersion = HawkbitCommonUtil.getFormattedNameVersion(sw.getName(), + sw.getVersion()); + softwareModule.setValue(softwareModNameVersion); + softwareModule.setDescription(softwareModNameVersion); + softwareModule.setId(sw.getName() + "-label"); + horizontalLayout.addComponent(softwareModule); + horizontalLayout.setExpandRatio(softwareModule, 1F); + if (isUnassignSoftModAllowed && permissionChecker.hasUpdateDistributionPermission() && !isTargetAssigned + && (isSoftModAvaiableForSoftType(alreadyAssignedSwModules, swModType))) { + horizontalLayout.addComponent(reassignSoftModule); + } + verticalLayout.addComponent(horizontalLayout); + } + + } + + return verticalLayout; + } + /** * @param value * @param alreadyAssignedSwModules * @return */ - protected SoftwareModule getSoftwareModule(final Label softwareModule, + protected SoftwareModule getSoftwareModule(final String softwareModule, final Set alreadyAssignedSwModules) { for (final SoftwareModule sw : alreadyAssignedSwModules) { - if (softwareModule.getValue().contains(sw.getName())) { + if (softwareModule.equals(sw.getName())) { return sw; } } @@ -256,15 +265,4 @@ public class SoftwareModuleDetailsTable extends Table { } return mandatoryLable; } - - private String getSwModuleName(final Set swModulesSet, final SoftwareModuleType swModType) { - final StringBuilder assignedSWModules = new StringBuilder(); - for (final SoftwareModule sw : swModulesSet) { - if (swModType.getKey().equals(sw.getType().getKey())) { - assignedSWModules.append(HawkbitCommonUtil.getFormattedNameVersion(sw.getName(), sw.getVersion())) - .append("
"); - } - } - return assignedSWModules.toString(); - } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java index 854347c11..fd5c1d59f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/detailslayout/SoftwareModuleMetadatadetailslayout.java @@ -47,7 +47,7 @@ public class SoftwareModuleMetadatadetailslayout extends Table { private SpPermissionChecker permissionChecker; - private SoftwareManagement softwareManagement; + private transient SoftwareManagement softwareManagement; private SwMetadataPopupLayout swMetadataPopupLayout; @@ -55,19 +55,33 @@ public class SoftwareModuleMetadatadetailslayout extends Table { private Long selectedSWModuleId; - private transient EntityFactory entityFactory; + private transient EntityFactory entityFactory; - public void init(final I18N i18n, final SpPermissionChecker permissionChecker, - final SoftwareManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout, - final EntityFactory entityFactory) { - this.i18n = i18n; - this.permissionChecker = permissionChecker; - this.softwareManagement = softwareManagement; - this.swMetadataPopupLayout = swMetadataPopupLayout; - this.entityFactory = entityFactory; - createSWMMetadataTable(); - addCustomGeneratedColumns(); - } + /** + * Initialize the layout. + * + * @param i18n + * the i18n service + * @param permissionChecker + * the permission checker service + * @param softwareManagement + * the software management service + * @param swMetadataPopupLayout + * the software module metadata popup layout + * @param entityFactory + * the entity factory service + */ + public void init(final I18N i18n, final SpPermissionChecker permissionChecker, + final SoftwareManagement softwareManagement, final SwMetadataPopupLayout swMetadataPopupLayout, + final EntityFactory entityFactory) { + this.i18n = i18n; + this.permissionChecker = permissionChecker; + this.softwareManagement = softwareManagement; + this.swMetadataPopupLayout = swMetadataPopupLayout; + this.entityFactory = entityFactory; + createSWMMetadataTable(); + addCustomGeneratedColumns(); + } /** * Populate software module metadata table. @@ -80,7 +94,7 @@ public class SoftwareModuleMetadatadetailslayout extends Table { return; } selectedSWModuleId = swModule.getId(); - final List swMetadataList = swModule.getMetadata(); + final List swMetadataList = softwareManagement.findSoftwareModuleMetadataBySoftwareModuleId(selectedSWModuleId); if (null != swMetadataList && !swMetadataList.isEmpty()) { swMetadataList.forEach(swMetadata -> setSWMetadataProperties(swMetadata)); } @@ -160,7 +174,7 @@ public class SoftwareModuleMetadatadetailslayout extends Table { } private void showMetadataDetails(final Long selectedSWModuleId, final String metadataKey) { - SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId); + final SoftwareModule swmodule = softwareManagement.findSoftwareModuleById(selectedSWModuleId); /* display the window */ UI.getCurrent().addWindow( swMetadataPopupLayout.getWindow(swmodule, diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java index b3b74836c..e8bb18e90 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTable.java @@ -26,8 +26,6 @@ import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.TableColumn; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.spring.events.EventBus; @@ -49,9 +47,9 @@ import com.vaadin.ui.themes.ValoTheme; */ public abstract class AbstractTable extends Table { - private static final long serialVersionUID = 4856562746502217630L; + private static final float DEFAULT_COLUMN_NAME_MIN_SIZE = 0.8F; - private static final Logger LOG = LoggerFactory.getLogger(AbstractTable.class); + private static final long serialVersionUID = 4856562746502217630L; @Autowired protected transient EventBus.SessionEventBus eventBus; @@ -89,6 +87,13 @@ public abstract class AbstractTable extends Table { eventBus.unsubscribe(this); } + /** + * Gets the selected item id or in multiselect mode a set of selected ids. + * + * @param table + * the table to retrieve the selected ID(s) + * @return the ID(s) which are selected in the table + */ public static Set getTableValue(final Table table) { @SuppressWarnings("unchecked") Set values = (Set) table.getValue(); @@ -351,7 +356,7 @@ public abstract class AbstractTable extends Table { } protected float getColumnNameMinimizedSize() { - return 0.8F; + return DEFAULT_COLUMN_NAME_MIN_SIZE; } /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java index 9d36e3de0..dbe377548 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTagToken.java @@ -12,6 +12,7 @@ import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @@ -43,6 +44,9 @@ import com.vaadin.ui.themes.ValoTheme; /** * Abstract class for target/ds tag token layout. + * + * @param + * the special entity */ public abstract class AbstractTagToken implements Serializable { @@ -54,7 +58,7 @@ public abstract class AbstractTagToken implements Serializ protected IndexedContainer container; - protected final transient Map tagDetails = new HashMap<>(); + protected final transient Map tagDetails = new ConcurrentHashMap<>(); protected final transient Map tokensAdded = new HashMap<>(); @@ -75,6 +79,9 @@ public abstract class AbstractTagToken implements Serializ @Autowired protected ManagementUIState managementUIState; + // BaseEntity implements Serializable so this entity is serializable. Maybe + // a sonar bug + @SuppressWarnings("squid:S1948") protected T selectedEntity; @PostConstruct @@ -140,10 +147,12 @@ public abstract class AbstractTagToken implements Serializ } protected void setContainerPropertValues(final Long tagId, final String tagName, final String tagColor) { - tagDetails.put(tagId, new TagData(tagId, tagName, tagColor)); - final Item item = container.addItem(tagId); - item.getItemProperty("id").setValue(tagId); - updateItem(tagName, tagColor, item); + final TagData tagData = tagDetails.putIfAbsent(tagId, new TagData(tagId, tagName, tagColor)); + if (tagData == null) { + final Item item = container.addItem(tagId); + item.getItemProperty("id").setValue(tagId); + updateItem(tagName, tagColor, item); + } } protected void updateItem(final String tagName, final String tagColor, final Item item) { @@ -211,11 +220,11 @@ public abstract class AbstractTagToken implements Serializ unassignTag(tagDetails.get(tokenId).getName()); } - } + private Property getItemNameProperty(final Object tokenId) { + final Item item = tokenField.getContainerDataSource().getItem(tokenId); + return item.getItemProperty("name"); + } - private Property getItemNameProperty(final Object tokenId) { - final Item item = tokenField.getContainerDataSource().getItem(tokenId); - return item.getItemProperty("name"); } private String getColor(final Object tokenId) { @@ -247,6 +256,7 @@ public abstract class AbstractTagToken implements Serializ protected void removeTokenItem(final Long tokenId, final String name) { tokenField.removeToken(tokenId); + tagDetails.remove(tokenId); setContainerPropertValues(tokenId, name, tokensAdded.get(tokenId).getColor()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTargetTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTargetTagToken.java index e74a331af..81ea9154c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTargetTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/AbstractTargetTagToken.java @@ -18,7 +18,10 @@ import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.annotation.EventBusListenerMethod; /** - * Abstract class for target tag token layout. + * /** Abstract class for target tag token layout. + * + * @param + * the entity type */ public abstract class AbstractTargetTagToken extends AbstractTagToken { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java index 88467d838..13e8eda9c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/DistributionTagToken.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.common.tagdetails; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -86,23 +85,11 @@ public class DistributionTagToken extends AbstractTagToken { @Override protected void unassignTag(final String tagName) { final DistributionSetTagAssignmentResult result = toggleAssignment(tagName); - if (result.getUnassigned() >= 1 && (isClickedTagListEmpty() || getClickedTagList().contains(tagName))) { + if (result.getUnassigned() >= 1) { eventBus.publish(this, ManagementUIEvent.UNASSIGN_DISTRIBUTION_TAG); } } - private Boolean isClickedTagListEmpty() { - if (getClickedTagList() == null || getClickedTagList() != null && !getClickedTagList().isEmpty()) { - return true; - } - return false; - } - - /* To Be Done : this implementation will vary in views */ - private List getClickedTagList() { - return new ArrayList<>(); - } - @Override protected Boolean isToggleTagAssignmentAllowed() { return checker.hasUpdateDistributionPermission(); @@ -121,6 +108,7 @@ public class DistributionTagToken extends AbstractTagToken { @Override protected void populateContainer() { container.removeAllItems(); + tagDetails.clear(); for (final DistributionSetTag tag : tagManagement.findAllDistributionSetTags()) { setContainerPropertValues(tag.getId(), tag.getName(), tag.getColour()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java index 2cd4ec978..2b4a853d0 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/tagdetails/TargetTagToken.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.ui.common.tagdetails; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -23,7 +22,6 @@ import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult; import org.eclipse.hawkbit.ui.management.event.ManagementUIEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; -import org.eclipse.hawkbit.ui.utils.UINotification; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.annotation.EventBusListenerMethod; @@ -46,9 +44,6 @@ public class TargetTagToken extends AbstractTargetTagToken { // To Be Done : have to set this value based on view??? private static final Boolean NOTAGS_SELECTED = Boolean.FALSE; - @Autowired - private UINotification uinotification; - @Autowired private transient TargetManagement targetManagement; @@ -85,23 +80,11 @@ public class TargetTagToken extends AbstractTargetTagToken { @Override protected void unassignTag(final String tagName) { final TargetTagAssignmentResult result = toggleAssignment(tagName); - if (result.getUnassigned() >= 1 && (isClickedTagListEmpty() || getClickedTagList().contains(tagName))) { + if (result.getUnassigned() >= 1) { eventBus.publish(this, ManagementUIEvent.UNASSIGN_TARGET_TAG); } } - private Boolean isClickedTagListEmpty() { - if (getClickedTagList() == null || getClickedTagList() != null && !getClickedTagList().isEmpty()) { - return true; - } - return false; - } - - /* To Be Done : this implementation will vary in views */ - private List getClickedTagList() { - return new ArrayList<>(); - } - @Override protected Boolean isToggleTagAssignmentAllowed() { return checker.hasUpdateTargetPermission(); @@ -120,6 +103,7 @@ public class TargetTagToken extends AbstractTargetTagToken { @Override protected void populateContainer() { container.removeAllItems(); + tagDetails.clear(); for (final TargetTag tag : tagManagement.findAllTargetTags()) { setContainerPropertValues(tag.getId(), tag.getName(), tag.getColour()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitErrorNotificationMessage.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitErrorNotificationMessage.java new file mode 100644 index 000000000..29bf822a8 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitErrorNotificationMessage.java @@ -0,0 +1,50 @@ +/** + * 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 org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; + +import com.vaadin.shared.Position; +import com.vaadin.ui.Notification; + +/** + * Notification message component for displaying errors in the UI. + */ +public class HawkbitErrorNotificationMessage extends Notification { + + private static final long serialVersionUID = -6512576924243195753L; + + /** + * Constructor of HawkbitErrorNotificationMessage + * + * @param style + * style of the notification message + * @param caption + * caption of the notification message + * @param description + * text which is displayed in the notification + * @param autoClose + * boolean if notification is closed after random click (true) or + * closed by clicking on the notification (false) + */ + public HawkbitErrorNotificationMessage(final String style, final String caption, final String description, + final boolean autoClose) { + super(caption); + setStyleName(style); + if (autoClose) { + setDelayMsec(SPUILabelDefinitions.SP_DELAY); + } else { + setDelayMsec(-1); + } + setHtmlContentAllowed(true); + setPosition(Position.BOTTOM_RIGHT); + setDescription(description); + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitUIErrorHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitUIErrorHandler.java new file mode 100644 index 000000000..cdbd04034 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/HawkbitUIErrorHandler.java @@ -0,0 +1,100 @@ +/** + * 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 static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_CLOSABLE; +import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_FAILURE; +import static com.vaadin.ui.themes.ValoTheme.NOTIFICATION_SMALL; + +import org.eclipse.hawkbit.ui.utils.I18N; +import org.eclipse.hawkbit.ui.utils.SpringContextHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Optional; +import com.vaadin.server.ClientConnector.ConnectorErrorEvent; +import com.vaadin.server.DefaultErrorHandler; +import com.vaadin.server.ErrorEvent; +import com.vaadin.server.Page; +import com.vaadin.shared.Connector; +import com.vaadin.ui.Component; +import com.vaadin.ui.Notification.Type; +import com.vaadin.ui.UI; + +/** + * Default handler for Hawkbit UI. + */ +public class HawkbitUIErrorHandler extends DefaultErrorHandler { + + private static final long serialVersionUID = 1L; + private static final Logger LOG = LoggerFactory.getLogger(HawkbitUIErrorHandler.class); + + private static final String STYLE = NOTIFICATION_FAILURE + " " + NOTIFICATION_SMALL + " " + NOTIFICATION_CLOSABLE; + + @Override + public void error(final ErrorEvent event) { + + final HawkbitErrorNotificationMessage message = buildNotification(getRootExceptionFrom(event)); + if (event instanceof ConnectorErrorEvent) { + final Connector connector = ((ConnectorErrorEvent) event).getConnector(); + if (connector instanceof UI) { + final UI uiInstance = (UI) connector; + uiInstance.access(() -> message.show(uiInstance.getPage())); + return; + } + } + + final Optional originError = getPageOriginError(event); + if (originError.isPresent()) { + message.show(originError.get()); + return; + } + + HawkbitErrorNotificationMessage.show(message.getCaption(), message.getDescription(), Type.HUMANIZED_MESSAGE); + } + + private static Throwable getRootExceptionFrom(final ErrorEvent event) { + return getRootCauseOf(event.getThrowable()); + } + + private static Throwable getRootCauseOf(final Throwable ex) { + + if (ex.getCause() != null) { + return getRootCauseOf(ex.getCause()); + } + + return ex; + } + + private static Optional getPageOriginError(final ErrorEvent event) { + + final Component errorOrigin = findAbstractComponent(event); + + if (errorOrigin != null && errorOrigin.getUI() != null) { + return Optional.fromNullable(errorOrigin.getUI().getPage()); + } + + return Optional.absent(); + } + + /** + * Method to build a notification based on an exception. + * + * @param ex + * the throwable + * @return a hawkbit error notification message + */ + protected HawkbitErrorNotificationMessage buildNotification(final Throwable ex) { + LOG.error("Error in UI: ", ex); + final I18N i18n = SpringContextHelper.getBean(I18N.class); + return new HawkbitErrorNotificationMessage(STYLE, i18n.get("caption.error"), + i18n.get("message.error.temp", ex.getClass().getSimpleName()), false); + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPNotificationMessage.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPNotificationMessage.java deleted file mode 100644 index 2685d2097..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPNotificationMessage.java +++ /dev/null @@ -1,83 +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 org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; - -import com.vaadin.server.Page; -import com.vaadin.shared.Position; -import com.vaadin.ui.Notification; - -/** - * Notification message component. - * - * - * - */ -public class SPNotificationMessage extends Notification { - - /** - * ID. - */ - private static final long serialVersionUID = -6512576924243195753L; - - /** - * Constructor. - */ - public SPNotificationMessage() { - super(""); - } - - /** - * Notification message component. - * - * @param styleName - * style name of message - * @param caption - * message caption - * @param description - * message description - * @param autoClose - * flag to indicate enable close option - * @param page - * current {@link Page} - */ - public void showNotification(final String styleName, final String caption, final String description, - final Boolean autoClose, final Page page) { - decorate(styleName, caption, description, autoClose); - this.show(page); - } - - /** - * Decorate. - * - * @param styleName - * style name of message - * @param caption - * message caption - * @param description - * message description - * @param autoClose - * flag to indicate enable close option - */ - private void decorate(final String styleName, final String caption, final String description, - final Boolean autoClose) { - setCaption(caption); - setDescription(description); - setStyleName(styleName); - setHtmlContentAllowed(true); - setPosition(Position.BOTTOM_RIGHT); - if (autoClose) { - setDelayMsec(SPUILabelDefinitions.SP_DELAY); - } else { - setDelayMsec(-1); - } - } - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java index f3f5c5a06..8161c2895 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIComponentProvider.java @@ -17,7 +17,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.ui.common.UserDetailsFormatter; import org.eclipse.hawkbit.ui.decorators.SPUIButtonDecorator; import org.eclipse.hawkbit.ui.decorators.SPUIComboBoxDecorator; -import org.eclipse.hawkbit.ui.decorators.SPUIHeaderLayoutDecorator; +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; @@ -104,7 +104,7 @@ public final class SPUIComponentProvider { * @return */ public static HorizontalLayout getHeaderLayout( - final Class tableHeaderLayoutDecorator) { + final Class tableHeaderLayoutDecorator) { // Do we really need this??? HorizontalLayout hLayout = getHorizontalLayout(new SPUIHorizontalLayout().getUiHorizontalLayout().getClass()); @@ -113,11 +113,11 @@ public final class SPUIComponentProvider { } try { - final SPUIHeaderLayoutDecorator layoutDecorator = tableHeaderLayoutDecorator.newInstance(); + final HeaderLayoutDecorator layoutDecorator = tableHeaderLayoutDecorator.newInstance(); hLayout = layoutDecorator.decorate(hLayout); } catch (final InstantiationException | IllegalAccessException exception) { - LOG.error("Error occured while creating horizontal decorator " + SPUIHeaderLayoutDecorator.class, + LOG.error("Error occured while creating horizontal decorator " + HeaderLayoutDecorator.class, exception); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIErrorHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIErrorHandler.java deleted file mode 100644 index e3d4881f0..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/components/SPUIErrorHandler.java +++ /dev/null @@ -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.components; - -import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; -import org.eclipse.hawkbit.ui.utils.I18N; -import org.eclipse.hawkbit.ui.utils.SpringContextHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.vaadin.server.DefaultErrorHandler; -import com.vaadin.server.ErrorEvent; -import com.vaadin.ui.Component; -import com.vaadin.ui.themes.ValoTheme; - -/** - * - * Default handler for SP UI. - * - * - * - * - * - */ -public class SPUIErrorHandler extends DefaultErrorHandler { - - /** - * Comment for serialVersionUID. - */ - private static final long serialVersionUID = 1877326479308824191L; - /** - * logger. - */ - private static final Logger LOG = LoggerFactory.getLogger(SPUIErrorHandler.class); - - @Override - public void error(final ErrorEvent event) { - final SPNotificationMessage notification = new SPNotificationMessage(); - // Build error style - final StringBuilder style = new StringBuilder(ValoTheme.NOTIFICATION_FAILURE); - style.append(' '); - style.append(ValoTheme.NOTIFICATION_SMALL); - style.append(' '); - style.append(ValoTheme.NOTIFICATION_CLOSABLE); - final I18N i18n = SpringContextHelper.getBean(I18N.class); - String exceptionName = null; - // From the exception trace we get the expected exception class name - for (Throwable error = event.getThrowable(); error != null; error = error.getCause()) { - exceptionName = HawkbitCommonUtil.getLastSequenceBySplitByDot(error.getClass().getName()); - LOG.error("Error in SP-UI:", error); - } - final Component errorOrgin = findAbstractComponent(event); - if (null != errorOrgin && errorOrgin.getUI() != null) { - notification.showNotification(style.toString(), i18n.get("caption.error"), - i18n.get("message.error.temp", new Object[] { exceptionName }), false, - errorOrgin.getUI().getPage()); - } - } -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/SPUIHeaderLayoutDecorator.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/HeaderLayoutDecorator.java similarity index 72% rename from hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/SPUIHeaderLayoutDecorator.java rename to hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/HeaderLayoutDecorator.java index f7de09ad7..a71bc9031 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/SPUIHeaderLayoutDecorator.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/HeaderLayoutDecorator.java @@ -13,13 +13,17 @@ import com.vaadin.ui.HorizontalLayout; /** * * - * + * Ui header layout decorater. */ -public interface SPUIHeaderLayoutDecorator { +@FunctionalInterface +public interface HeaderLayoutDecorator { /** + * decorate the header + * * @param layout - * @return + * the layout + * @return the decorated layout */ HorizontalLayout decorate(HorizontalLayout layout); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/SPUIButtonDecorator.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/SPUIButtonDecorator.java index dd6f928d7..05d1f8a0a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/SPUIButtonDecorator.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/decorators/SPUIButtonDecorator.java @@ -17,6 +17,7 @@ import com.vaadin.ui.Button; * * */ +@FunctionalInterface public interface SPUIButtonDecorator { /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java index 2a12bc859..65e52d448 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/CreateUpdateDistSetTypeLayout.java @@ -9,7 +9,6 @@ package org.eclipse.hawkbit.ui.distributions.disttype; import java.util.List; -import java.util.Map; import java.util.Set; import org.eclipse.hawkbit.repository.DistributionSetManagement; @@ -27,8 +26,6 @@ import org.eclipse.hawkbit.ui.layouts.CreateUpdateTypeLayout; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; @@ -59,8 +56,6 @@ import com.vaadin.ui.themes.ValoTheme; public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout { private static final long serialVersionUID = -5169398523815877767L; - private static final Logger LOG = LoggerFactory.getLogger(CreateUpdateDistSetTypeLayout.class); - private static final String DIST_TYPE_NAME = "name"; private static final String DIST_TYPE_DESCRIPTION = "description"; private static final String DIST_TYPE_MANDATORY = "mandatory"; @@ -84,8 +79,6 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout { private IndexedContainer originalSelectedTableContainer; - private Map mandatoryCheckboxMap; - @Override protected void createRequiredComponents() { @@ -152,9 +145,9 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout { twinColumnLayout.setComponentAlignment(sourceTable, Alignment.MIDDLE_LEFT); twinColumnLayout.setComponentAlignment(selectButtonLayout, Alignment.MIDDLE_CENTER); twinColumnLayout.setComponentAlignment(selectedTable, Alignment.MIDDLE_RIGHT); - twinColumnLayout.setExpandRatio(sourceTable, 0.45f); - twinColumnLayout.setExpandRatio(selectButtonLayout, 0.07f); - twinColumnLayout.setExpandRatio(selectedTable, 0.48f); + twinColumnLayout.setExpandRatio(sourceTable, 0.45F); + twinColumnLayout.setExpandRatio(selectButtonLayout, 0.07F); + twinColumnLayout.setExpandRatio(selectedTable, 0.48F); sourceTable.setVisibleColumns(new Object[] { DIST_TYPE_NAME }); return twinColumnLayout; } @@ -226,7 +219,7 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout { sourceTable.setVisibleColumns(new Object[] { DIST_TYPE_NAME }); sourceTable.setColumnHeaders(i18n.get("header.dist.twintable.available")); - sourceTable.setColumnExpandRatio(DIST_TYPE_NAME, 1.0f); + sourceTable.setColumnExpandRatio(DIST_TYPE_NAME, 1.0F); getSourceTableData(); addTooltip(); sourceTable.select(sourceTable.firstItemId()); @@ -413,7 +406,7 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout { } } - private void checkMandatoryAndAddMandatoryModuleType(final DistributionSetType updateDistSetType, + private static void checkMandatoryAndAddMandatoryModuleType(final DistributionSetType updateDistSetType, final Boolean isMandatory, final SoftwareModuleType swModuleType) { if (isMandatory) { updateDistSetType.addMandatoryModuleType(swModuleType); @@ -488,7 +481,7 @@ public class CreateUpdateDistSetTypeLayout extends CreateUpdateTypeLayout { * * @return */ - private LazyQueryContainer getDistSetTypeLazyQueryContainer() { + private static LazyQueryContainer getDistSetTypeLazyQueryContainer() { final LazyQueryContainer disttypeContainer = HawkbitCommonUtil.createLazyQueryContainer( new BeanQueryFactory(DistributionSetTypeBeanQuery.class)); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java index 03a86c44d..06b23c51b 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetDetails.java @@ -17,7 +17,6 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareManagement; 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.SoftwareModuleIdName; 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.components.SPUIComponentProvider; 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.SoftwareModuleAssignmentDiscardEvent; import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState; @@ -47,6 +45,7 @@ import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.TabSheet; import com.vaadin.ui.UI; @@ -67,8 +66,6 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet private static final String SOFT_MODULE = "softwareModule"; - private static final String UNASSIGN_SOFT_MODULE = "unassignSoftModule"; - @Autowired private ManageDistUIState manageDistUIState; @@ -83,37 +80,20 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet @Autowired private transient DistributionSetManagement distributionSetManagement; - + @Autowired private DsMetadataPopupLayout dsMetadataPopupLayout; - + @Autowired - private EntityFactory entityFactory; + private transient EntityFactory entityFactory; private SoftwareModuleDetailsTable softwareModuleTable; - + private DistributionSetMetadatadetailslayout dsMetadataTable; private VerticalLayout tagsLayout; - + private final Map assignedSWModule = new HashMap<>(); - - - @EventBusListenerMethod(scope = EventScope.SESSION) - void onEvent(final MetadataEvent event) { - UI.getCurrent() - .access(() -> { - 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. @@ -124,8 +104,8 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet softwareModuleTable.init(getI18n(), true, getPermissionChecker(), distributionSetManagement, getEventBus(), manageDistUIState); dsMetadataTable = new DistributionSetMetadatadetailslayout(); - dsMetadataTable.init(getI18n(), getPermissionChecker(),distributionSetManagement, - dsMetadataPopupLayout,entityFactory); + dsMetadataTable.init(getI18n(), getPermissionChecker(), distributionSetManagement, dsMetadataPopupLayout, + entityFactory); super.init(); } @@ -141,7 +121,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet populateTags(); populateMetadataDetails(); } - + private void populateModule() { softwareModuleTable.populateModule(getSelectedBaseEntity()); showUnsavedAssignment(); @@ -182,27 +162,25 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet for (final Map.Entry entry : assignedSWModule.entrySet()) { item = softwareModuleTable.getContainerDataSource().getItem(entry.getKey()); if (item != null) { - item.getItemProperty(SOFT_MODULE) - .setValue(HawkbitCommonUtil.getFormatedLabel(entry.getValue().toString())); - assignSoftModuleButton(item, entry); - + item.getItemProperty(SOFT_MODULE).setValue(createSoftModuleLayout(entry.getValue().toString())); } } } } - private void assignSoftModuleButton(final Item item, final Map.Entry entry) { + private Button assignSoftModuleButton(final String softwareModuleName) { if (getPermissionChecker().hasUpdateDistributionPermission() && distributionSetManagement .findDistributionSetById(manageDistUIState.getLastSelectedDistribution().get().getId()) .getAssignedTargets().isEmpty()) { - final Button reassignSoftModule = SPUIComponentProvider.getButton(entry.getKey(), "", "", "", true, + final Button reassignSoftModule = SPUIComponentProvider.getButton(softwareModuleName, "", "", "", true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class); reassignSoftModule.setEnabled(false); - item.getItemProperty(UNASSIGN_SOFT_MODULE).setValue(reassignSoftModule); + return reassignSoftModule; } + return null; } - private String getUnsavedAssigedSwModule(final String name, final String version) { + private static String getUnsavedAssigedSwModule(final String name, final String version) { return HawkbitCommonUtil.getFormattedNameVersion(name, version); } @@ -217,7 +195,7 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet * type is drroped, then add to the list. */ - if (module.getType().getMaxAssignments() == Integer.MAX_VALUE) { + if (module.getType().getMaxAssignments() > 1) { assignedSWModule.get(module.getType().getName()).append("
").append("") .append(getUnsavedAssigedSwModule(module.getName(), module.getVersion())).append(""); } @@ -240,14 +218,27 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet for (final Map.Entry entry : assignedSWModule.entrySet()) { final Item item = softwareModuleTable.getContainerDataSource().getItem(entry.getKey()); if (item != null) { - item.getItemProperty(SOFT_MODULE) - .setValue(HawkbitCommonUtil.getFormatedLabel(entry.getValue().toString())); - assignSoftModuleButton(item, entry); - + item.getItemProperty(SOFT_MODULE).setValue(createSoftModuleLayout(entry.getValue().toString())); } } } + private VerticalLayout createSoftModuleLayout(final String softwareModuleName) { + final VerticalLayout verticalLayout = new VerticalLayout(); + final HorizontalLayout horizontalLayout = new HorizontalLayout(); + horizontalLayout.setSizeFull(); + final Label softwareModule = HawkbitCommonUtil.getFormatedLabel(HawkbitCommonUtil.SP_STRING_EMPTY); + final Button reassignSoftModule = assignSoftModuleButton(softwareModuleName); + softwareModule.setValue(softwareModuleName); + softwareModule.setDescription(softwareModuleName); + softwareModule.setId(softwareModuleName + "-label"); + horizontalLayout.addComponent(softwareModule); + horizontalLayout.setExpandRatio(softwareModule, 1F); + horizontalLayout.addComponent(reassignSoftModule); + verticalLayout.addComponent(horizontalLayout); + return verticalLayout; + } + private VerticalLayout createSoftwareModuleTab() { final VerticalLayout softwareLayout = getTabLayout(); softwareLayout.setSizeFull(); @@ -271,12 +262,12 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet updateDistributionSetDetailsLayout(null, null); } } - + @Override - protected void populateMetadataDetails(){ + protected void populateMetadataDetails() { dsMetadataTable.populateDSMetadata(getSelectedBaseEntity()); - } - + } + private void updateDistributionSetDetailsLayout(final String type, final Boolean isMigrationRequired) { final VerticalLayout detailsTabLayout = getDetailsLayout(); detailsTabLayout.removeAllComponents(); @@ -403,26 +394,18 @@ public class DistributionSetDetails extends AbstractNamedVersionedEntityTableDet protected Boolean isMetadataIconToBeDisplayed() { return true; } - - @Override - protected String getShowMetadataButtonId() { - DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() ? manageDistUIState - .getLastSelectedDistribution().get() : null; - return SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + lastselectedDistDS.getName() + "." - + lastselectedDistDS.getVersion(); - } - - private boolean isDistributionSetSelected(DistributionSet ds) { - DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() ? manageDistUIState - .getLastSelectedDistribution().get() : null; + + private boolean isDistributionSetSelected(final DistributionSet ds) { + final DistributionSetIdName lastselectedDistDS = manageDistUIState.getLastSelectedDistribution().isPresent() + ? manageDistUIState.getLastSelectedDistribution().get() : null; return ds != null && lastselectedDistDS != null && lastselectedDistDS.getName().equals(ds.getName()) && lastselectedDistDS.getVersion().endsWith(ds.getVersion()); } - @Override - protected void showMetadata(ClickEvent event) { - DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); - UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds,null)); + protected void showMetadata(final ClickEvent event) { + final DistributionSet ds = distributionSetManagement + .findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); + UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java index 58b64d1b0..6cda2cd16 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTable.java @@ -21,6 +21,9 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SpPermissionChecker; 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.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleIdName; @@ -105,7 +108,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable visibleItemIds = (List) 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) events); + } + } + @Override protected String getTableId() { return SPUIComponentIdProvider.DIST_TABLE_ID; @@ -189,10 +219,10 @@ public class DistributionSetTable extends AbstractNamedVersionTable> map, final SoftwareModule softwareModule, final SoftwareModuleIdName softwareModuleIdName) { - if (softwareModule.getType().getMaxAssignments() == Integer.MAX_VALUE) { + if (softwareModule.getType().getMaxAssignments() > 1) { if (!map.containsKey(softwareModule.getType().getId())) { map.put(softwareModule.getType().getId(), new HashSet()); } @@ -334,9 +364,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable updateDistributionInTable(event.getEntity())); } @EventBusListenerMethod(scope = EventScope.SESSION) @@ -479,8 +511,9 @@ public class DistributionSetTable extends AbstractNamedVersionTable showMetadataDetails(((DistributionSetIdName) itemId).getId())); + manageMetaDataBtn + .addClickListener(event -> showMetadataDetails(((DistributionSetIdName) itemId).getId())); return manageMetaDataBtn; } }); } - @Override protected List getTableVisibleColumns() { @@ -506,7 +539,7 @@ public class DistributionSetTable extends AbstractNamedVersionTable events) { + final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource(); + final List visibleItemIds = (List) 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 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); + } + } + } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java index 2041944d4..8b035de45 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DsMetadataPopupLayout.java @@ -16,8 +16,6 @@ import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; 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 com.vaadin.spring.annotation.SpringComponent; @@ -36,25 +34,25 @@ public class DsMetadataPopupLayout extends AbstractMetadataPopupLayout getMetadataList() { return getSelectedEntity().getMetadata(); } - + /** * Update metadata for DistributionSet. */ @Override - protected void deleteMetadata(DistributionSet entity, String key, String value) { - DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value); + protected void deleteMetadata(final DistributionSet entity, final String key, final String value) { + final DistributionSetMetadata dsMetaData = entityFactory.generateDistributionSetMetadata(entity, key, value); distributionSetManagement.deleteDistributionSetMetadata(entity, key); - eventBus.publish(this, new MetadataEvent(MetadataUIEvent.DELETE_DISTRIBUTION_SET_METADATA, dsMetaData)); } - + @Override protected boolean hasCreatePermission() { return permChecker.hasCreateDistributionPermission(); } - + @Override protected boolean hasUpdatePermission() { return permChecker.hasUpdateDistributionPermission(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/ManageDistBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/ManageDistBeanQuery.java index a262f0d20..efe28beb5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/ManageDistBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/ManageDistBeanQuery.java @@ -42,7 +42,7 @@ import com.google.common.base.Strings; public class ManageDistBeanQuery extends AbstractBeanQuery { 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 transient DistributionSetManagement distributionSetManagement; private transient Page firstPageDistributionSets = null; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java index f82bc5c01..2436de9e5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/MetadataEvent.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.ui.distributions.event; import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; + /** * * Metadata Events. @@ -18,21 +19,21 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; public class MetadataEvent { 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 SoftwareModuleMetadata softwareModuleMetadata; - public MetadataEvent(MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) { + public MetadataEvent(final MetadataUIEvent metadataUIEvent, final DistributionSetMetadata distributionSetMetadata) { this.metadataUIEvent = metadataUIEvent; this.distributionSetMetadata = distributionSetMetadata; } - public MetadataEvent(MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) { + public MetadataEvent(final MetadataUIEvent metadataUIEvent, final SoftwareModuleMetadata softwareModuleMetadata) { this.metadataUIEvent = metadataUIEvent; this.softwareModuleMetadata = softwareModuleMetadata; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java index 6cec80028..adf444b46 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleDetails.java @@ -49,49 +49,50 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay @Autowired private ManageDistUIState manageDistUIState; - + @Autowired private transient SoftwareManagement softwareManagement; - + @Autowired private SwMetadataPopupLayout swMetadataPopupLayout; - + @Autowired - private EntityFactory entityFactory; - + private transient EntityFactory entityFactory; + private SoftwareModuleMetadatadetailslayout swmMetadataTable; - /** + /** * softwareLayout Initialize the component. */ @Override protected void init() { swmMetadataTable = new SoftwareModuleMetadatadetailslayout(); - swmMetadataTable.init(getI18n(), getPermissionChecker(),softwareManagement,swMetadataPopupLayout,entityFactory); + swmMetadataTable.init(getI18n(), getPermissionChecker(), softwareManagement, swMetadataPopupLayout, + entityFactory); super.init(); } - + /** * MetadataEvent. * * @param event * as instance of {@link MetadataEvent} */ - + @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final MetadataEvent event) { - UI.getCurrent() - .access(() -> { - SoftwareModuleMetadata softwareModuleMetadata = event.getSoftwareModuleMetadata(); - if (softwareModuleMetadata != null - && isSoftwareModuleSelected(softwareModuleMetadata.getSoftwareModule())) { - if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA) { - swmMetadataTable.createMetadata(event.getSoftwareModuleMetadata().getKey()); - } else if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA) { - swmMetadataTable.deleteMetadata(event.getSoftwareModuleMetadata().getKey()); - } - } - }); + UI.getCurrent().access(() -> { + final SoftwareModuleMetadata softwareModuleMetadata = event.getSoftwareModuleMetadata(); + if (softwareModuleMetadata != null + && isSoftwareModuleSelected(softwareModuleMetadata.getSoftwareModule())) { + if (event.getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.CREATE_SOFTWARE_MODULE_METADATA) { + swmMetadataTable.createMetadata(event.getSoftwareModuleMetadata().getKey()); + } else if (event + .getMetadataUIEvent() == MetadataEvent.MetadataUIEvent.DELETE_SOFTWARE_MODULE_METADATA) { + swmMetadataTable.deleteMetadata(event.getSoftwareModuleMetadata().getKey()); + } + } + }); } @EventBusListenerMethod(scope = EventScope.SESSION) @@ -119,7 +120,7 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay detailsTab.addTab(createDescriptionLayout(), getI18n().get("caption.tab.description"), null); detailsTab.addTab(createLogLayout(), getI18n().get("caption.logs.tab"), null); detailsTab.addTab(swmMetadataTable, getI18n().get("caption.metadata"), null); - } + } @Override protected String getDefaultCaption() { @@ -149,10 +150,10 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay private void populateDetails() { String maxAssign = HawkbitCommonUtil.SP_STRING_EMPTY; if (getSelectedBaseEntity() != null) { - if (getSelectedBaseEntity().getType().getMaxAssignments() == Integer.MAX_VALUE) { - maxAssign = getI18n().get("label.multiAssign.type"); - } else { + if (getSelectedBaseEntity().getType().getMaxAssignments() == 1) { maxAssign = getI18n().get("label.singleAssign.type"); + } else { + maxAssign = getI18n().get("label.multiAssign.type"); } updateSwModuleDetailsLayout(getSelectedBaseEntity().getType().getName(), getSelectedBaseEntity().getVendor(), maxAssign); @@ -196,15 +197,15 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay protected String getDetailsHeaderCaptionId() { return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID; } - + @Override protected void populateMetadataDetails() { swmMetadataTable.populateSMMetadata(getSelectedBaseEntity()); } - private boolean isSoftwareModuleSelected(SoftwareModule softwareModule) { - final Long selectedDistSWModuleId = manageDistUIState.getSelectedBaseSwModuleId().isPresent() ? manageDistUIState - .getSelectedBaseSwModuleId().get() : null; + private boolean isSoftwareModuleSelected(final SoftwareModule softwareModule) { + final Long selectedDistSWModuleId = manageDistUIState.getSelectedBaseSwModuleId().isPresent() + ? manageDistUIState.getSelectedBaseSwModuleId().get() : null; return softwareModule != null && selectedDistSWModuleId != null && selectedDistSWModuleId.equals(softwareModule.getId()); } @@ -213,17 +214,10 @@ public class SwModuleDetails extends AbstractNamedVersionedEntityTableDetailsLay protected Boolean isMetadataIconToBeDisplayed() { return true; } - - @Override - protected String getShowMetadataButtonId() { - SoftwareModule selectedBaseEntity = getSelectedBaseEntity(); - return SPUIComponentIdProvider.SW_TABLE_MANAGE_METADATA_ID + "." + selectedBaseEntity.getName() + "." - + selectedBaseEntity.getVersion(); - } @Override - protected void showMetadata(ClickEvent event) { - SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(getSelectedBaseEntityId()); + protected void showMetadata(final ClickEvent event) { + final SoftwareModule swmodule = softwareManagement.findSoftwareModuleWithDetails(getSelectedBaseEntityId()); UI.getCurrent().addWindow(swMetadataPopupLayout.getWindow(swmodule, null)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filter/FilterExpression.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filter/FilterExpression.java index 1aaafd905..853c6f095 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filter/FilterExpression.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filter/FilterExpression.java @@ -13,11 +13,9 @@ package org.eclipse.hawkbit.ui.filter; * mechanism. The filter expression can evaluate if e.g. Targets should * currently be added to the target list or if the current enabled filtered will * filter the target and not show the newly created target. - * - * - * * */ +@FunctionalInterface public interface FilterExpression { /** diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CreateOrUpdateFilterHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CreateOrUpdateFilterHeader.java index b785ae8b6..1023d98ed 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CreateOrUpdateFilterHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CreateOrUpdateFilterHeader.java @@ -60,8 +60,7 @@ import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.ValoTheme; /** - * - * + * A Vaadin layout for create or update the target filter. */ @SpringComponent @ViewScope @@ -494,11 +493,7 @@ public class CreateOrUpdateFilterHeader extends VerticalLayout implements Button if (filterManagementUIState.isCreateFilterViewDisplayed() && !doesAlreadyExists()) { createTargetFilterQuery(); } else { - if (!nameTextField.getValue().equals(oldFilterName) && !doesAlreadyExists()) { - updateCustomFilter(); - } else { - updateCustomFilter(); - } + updateCustomFilter(); } } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java index 35f88f5a1..80c9b0497 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/CustomTargetBeanQuery.java @@ -155,9 +155,9 @@ public class CustomTargetBeanQuery extends AbstractBeanQuery { size = getTargetManagement().countTargetByTargetFilterQuery(filterQuery); } getFilterManagementUIState().setTargetsCountAll(size); - if (size > SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { - getFilterManagementUIState().setTargetsTruncated(size - SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES); - size = SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES; + if (size > SPUIDefinitions.MAX_TABLE_ENTRIES) { + getFilterManagementUIState().setTargetsTruncated(size - SPUIDefinitions.MAX_TABLE_ENTRIES); + size = SPUIDefinitions.MAX_TABLE_ENTRIES; } else { getFilterManagementUIState().setTargetsTruncated(null); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java index 4700b48eb..c82467425 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/footer/TargetFilterCountMessageLabel.java @@ -93,7 +93,7 @@ public class TargetFilterCountMessageLabel extends Label { // set the icon setIcon(FontAwesome.INFO_CIRCLE); setDescription(i18n.get("label.target.filter.truncated", filterManagementUIState.getTargetsTruncated(), - SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES)); + SPUIDefinitions.MAX_TABLE_ENTRIES)); } else { setIcon(null); @@ -102,8 +102,8 @@ public class TargetFilterCountMessageLabel extends Label { targetMessage.append(totalTargets); targetMessage.append(HawkbitCommonUtil.SP_STRING_SPACE); targetMessage.append(i18n.get("label.filter.shown")); - if (totalTargets > SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { - targetMessage.append(SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES); + if (totalTargets > SPUIDefinitions.MAX_TABLE_ENTRIES) { + targetMessage.append(SPUIDefinitions.MAX_TABLE_ENTRIES); } else { targetMessage.append(HawkbitCommonUtil.SP_STRING_SPACE); targetMessage.append(totalTargets); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java index 069b9b407..a4b8c6a86 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionAddUpdateWindowLayout.java @@ -9,7 +9,9 @@ package org.eclipse.hawkbit.ui.management.dstable; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import javax.annotation.PostConstruct; @@ -21,10 +23,12 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.ui.common.CommonDialogWindow; +import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.DistributionSetTypeBeanQuery; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.decorators.SPUIWindowDecorator; +import org.eclipse.hawkbit.ui.distributions.dstable.DistributionSetTable; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; import org.eclipse.hawkbit.ui.management.event.DragEvent; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; @@ -33,6 +37,7 @@ import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; 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.SpringContextHelper; import org.eclipse.hawkbit.ui.utils.UINotification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -80,7 +85,6 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent { @Autowired private transient EntityFactory entityFactory; - private TextField distNameTextField; private TextField distVersionTextField; private TextArea descTextArea; @@ -233,7 +237,10 @@ public class DistributionAddUpdateWindowLayout extends CustomComponent { notificationMessage.displaySuccess(i18n.get("message.new.dist.save.success", new Object[] { newDist.getName(), newDist.getVersion() })); - eventBus.publish(this, new DistributionTableEvent(BaseEntityEventType.NEW_ENTITY, newDist)); + final Set s = new HashSet<>(); + s.add(new DistributionSetIdName(newDist.getId(), newDist.getName(), newDist.getVersion())); + final DistributionSetTable distributionSetTable = SpringContextHelper.getBean(DistributionSetTable.class); + distributionSetTable.setValue(s); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java index 63ed91250..672cc0a1c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionBeanQuery.java @@ -41,7 +41,7 @@ import com.google.common.base.Strings; public class DistributionBeanQuery extends AbstractBeanQuery { private static final long serialVersionUID = 5862679853949173536L; - private Sort sort = new Sort(Direction.ASC, "name", "version"); + private Sort sort = new Sort(Direction.ASC, "createdAt"); private Collection distributionTags; private String searchText; private String pinnedControllerId; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java index e59820e9c..9992b09e2 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionDetails.java @@ -11,7 +11,6 @@ package org.eclipse.hawkbit.ui.management.dstable; import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.DistributionSetMetadata; import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractNamedVersionedEntityTableDetailsLayout; import org.eclipse.hawkbit.ui.common.detailslayout.DistributionSetMetadatadetailslayout; @@ -19,7 +18,6 @@ import org.eclipse.hawkbit.ui.common.detailslayout.SoftwareModuleDetailsTable; import org.eclipse.hawkbit.ui.common.tagdetails.DistributionTagToken; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.distributions.dstable.DsMetadataPopupLayout; -import org.eclipse.hawkbit.ui.distributions.event.MetadataEvent; import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; @@ -53,48 +51,32 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail @Autowired private DistributionTagToken distributionTagToken; - + @Autowired - private transient DistributionSetManagement distributionSetManagement; - + private transient DistributionSetManagement distributionSetManagement; + @Autowired private DsMetadataPopupLayout dsMetadataPopupLayout; - + @Autowired - private EntityFactory entityFactory; + private transient EntityFactory entityFactory; private SoftwareModuleDetailsTable softwareModuleTable; private DistributionSetMetadatadetailslayout dsMetadataTable; - + @Override protected void init() { softwareModuleTable = new SoftwareModuleDetailsTable(); softwareModuleTable.init(getI18n(), false, getPermissionChecker(), null, null, null); - + dsMetadataTable = new DistributionSetMetadatadetailslayout(); - dsMetadataTable.init(getI18n(), getPermissionChecker(),distributionSetManagement, - dsMetadataPopupLayout,entityFactory); - + dsMetadataTable.init(getI18n(), getPermissionChecker(), distributionSetManagement, dsMetadataPopupLayout, + entityFactory); + super.init(); } - @EventBusListenerMethod(scope = EventScope.SESSION) - void onEvent(final MetadataEvent event) { - UI.getCurrent() - .access(() -> { - 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()); - } - } - }); - } - - @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final DistributionTableEvent distributionTableEvent) { onBaseEntityEvent(distributionTableEvent); @@ -156,12 +138,11 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail populateMetadataDetails(); } - - + @Override - protected void populateMetadataDetails(){ + protected void populateMetadataDetails() { dsMetadataTable.populateDSMetadata(getSelectedBaseEntity()); - } + } private void populateDetails(final DistributionSet ds) { if (ds != null) { @@ -206,30 +187,24 @@ public class DistributionDetails extends AbstractNamedVersionedEntityTableDetail protected String getDetailsHeaderCaptionId() { return SPUIComponentIdProvider.DISTRIBUTION_DETAILS_HEADER_LABEL_ID; } - + @Override protected Boolean isMetadataIconToBeDisplayed() { return true; } - - @Override - protected String getShowMetadataButtonId() { - DistributionSetIdName lastselectedDistDS = managementUIState.getLastSelectedDistribution().isPresent() ? managementUIState - .getLastSelectedDistribution().get() : null; - return SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + lastselectedDistDS.getName() + "." - + lastselectedDistDS.getVersion(); - } - private boolean isDistributionSetSelected(DistributionSet ds) { - DistributionSetIdName lastselectedManageDS = managementUIState.getLastSelectedDistribution().isPresent() ? managementUIState - .getLastSelectedDistribution().get() : null; - return ds!=null && lastselectedManageDS != null && lastselectedManageDS.getName().equals(ds.getName()) + + private boolean isDistributionSetSelected(final DistributionSet ds) { + final DistributionSetIdName lastselectedManageDS = managementUIState.getLastSelectedDistribution().isPresent() + ? managementUIState.getLastSelectedDistribution().get() : null; + return ds != null && lastselectedManageDS != null && lastselectedManageDS.getName().equals(ds.getName()) && lastselectedManageDS.getVersion().endsWith(ds.getVersion()); } @Override - protected void showMetadata(ClickEvent event) { - DistributionSet ds = distributionSetManagement.findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); - UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds,null)); + protected void showMetadata(final ClickEvent event) { + final DistributionSet ds = distributionSetManagement + .findDistributionSetByIdWithDetails(getSelectedBaseEntityId()); + UI.getCurrent().addWindow(dsMetadataPopupLayout.getWindow(ds, null)); } - + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java index f6cd80853..e4313dd80 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTable.java @@ -21,6 +21,9 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SpPermissionChecker; 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.DistributionSetTagAssignmentResult; import org.eclipse.hawkbit.repository.model.Target; @@ -90,18 +93,18 @@ public class DistributionTable extends AbstractNamedVersionTable events) { + final Object firstEvent = events.get(0); + if (DistributionDeletedEvent.class.isInstance(firstEvent)) { + onDistributionDeleteEvent((List) events); + } else if (DistributionCreatedEvent.class.isInstance(firstEvent) + && ((DistributionCreatedEvent) firstEvent).getEntity().isComplete()) { + refreshDistributions(); + } + + } + + @EventBusListenerMethod(scope = EventScope.SESSION) + void onEvents(final DistributionSetUpdateEvent event) { + final DistributionSet ds = event.getEntity(); + + final List visibleItemIds = (List) getVisibleItemIds(); + + final Boolean dsVisible = visibleItemIds.stream().filter(e -> e.getId().equals(ds.getId())).findFirst() + .isPresent(); + + if ((ds.isComplete() && !dsVisible)) { + refreshDistributions(); + } else if ((!ds.isComplete() && dsVisible)) { + refreshDistributions(); + if (ds.getId().equals(managementUIState.getLastSelectedDsIdName().getId())) { + managementUIState.setLastSelectedDistribution(null); + managementUIState.setLastSelectedEntity(null); + } + + } else if (dsVisible) { + UI.getCurrent().access(() -> updateDistributionInTable(event.getEntity())); + } + final DistributionSetIdName lastSelectedDsIdName = managementUIState.getLastSelectedDsIdName(); + // 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)); + } + } + /** * DistributionTableFilterEvent. * @@ -229,27 +273,26 @@ public class DistributionTable extends AbstractNamedVersionTable showMetadataDetails(itemId)); - iconLayout.addComponent((Button)getPinButton(itemId)); + iconLayout.addComponent((Button) getPinButton(itemId)); iconLayout.addComponent(manageMetaDataBtn); return iconLayout; } - + }); } - - + private String getNameAndVerion(final Object itemId) { final Item item = getItem(itemId); final String name = (String) item.getItemProperty(SPUILabelDefinitions.VAR_NAME).getValue(); final String version = (String) item.getItemProperty(SPUILabelDefinitions.VAR_VERSION).getValue(); return name + "." + version; } - - private Button createManageMetadataButton(String nameVersionStr) { + + private Button createManageMetadataButton(final String nameVersionStr) { final Button manageMetadataBtn = SPUIComponentProvider.getButton( SPUIComponentIdProvider.DS_TABLE_MANAGE_METADATA_ID + "." + nameVersionStr, "", "", null, false, FontAwesome.LIST_ALT, SPUIButtonStyleSmallNoBorder.class); @@ -281,9 +324,9 @@ public class DistributionTable extends AbstractNamedVersionTable events) { + final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource(); + final List visibleItemIds = (List) 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 reSelectItemsAfterDeletionEvent() { + Set 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); + } + } + } + + 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 refreshOnDelete() { + final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource(); + final int size = dsContainer.size(); + refreshTablecontainer(); + if (size != 0) { + setData(SPUIDefinitions.DATA_AVAILABLE); + } + } + + private void refreshTablecontainer() { + final LazyQueryContainer dsContainer = (LazyQueryContainer) getContainerDataSource(); + dsContainer.refresh(); + selectRow(); + } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java index fccee7cb5..6cf01410d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/CountMessageLabel.java @@ -174,7 +174,7 @@ public class CountMessageLabel extends Label { // set the icon setIcon(FontAwesome.INFO_CIRCLE); setDescription(i18n.get("label.target.filter.truncated", managementUIState.getTargetsTruncated(), - SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES)); + SPUIDefinitions.MAX_TABLE_ENTRIES)); totalTargetTableEnteries += managementUIState.getTargetsTruncated(); } else { setIcon(null); @@ -184,9 +184,9 @@ public class CountMessageLabel extends Label { final StringBuilder message = new StringBuilder(i18n.get("label.target.filter.count")); message.append(managementUIState.getTargetsCountAll()); message.append(HawkbitCommonUtil.SP_STRING_SPACE); - if (totalTargetTableEnteries > SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { + if (totalTargetTableEnteries > SPUIDefinitions.MAX_TABLE_ENTRIES) { message.append(i18n.get("label.filter.shown")); - message.append(SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES); + message.append(SPUIDefinitions.MAX_TABLE_ENTRIES); } else { if (!targFilParams.hasFilter()) { message.append(i18n.get("label.filter.shown")); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/ManangementConfirmationWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/ManangementConfirmationWindowLayout.java index 1a9d3572f..e4c56b165 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/ManangementConfirmationWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/footer/ManangementConfirmationWindowLayout.java @@ -387,7 +387,6 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin managementUIState.getTargetTableFilters().getPinnedDistId() .ifPresent(distId -> unPinDeletedDS(deletedIds, distId)); - eventBus.publish(this, SaveActionWindowEvent.DELETED_DISTRIBUTIONS); managementUIState.getDeletedDistributionList().clear(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java index 982e9d75b..116853afb 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/BulkUploadHandler.java @@ -33,6 +33,7 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.tagdetails.AbstractTagToken.TagData; +import org.eclipse.hawkbit.ui.components.HawkbitErrorNotificationMessage; import org.eclipse.hawkbit.ui.management.event.BulkUploadValidationMessageEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent; import org.eclipse.hawkbit.ui.management.event.TargetTableEvent.TargetComponentEvent; @@ -40,12 +41,13 @@ import org.eclipse.hawkbit.ui.management.state.ManagementUIState; import org.eclipse.hawkbit.ui.management.state.TargetBulkUpload; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.I18N; +import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SpringContextHelper; -import org.eclipse.hawkbit.ui.utils.UINotification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.vaadin.spring.events.EventBus; +import com.vaadin.server.Page; import com.vaadin.ui.Alignment; import com.vaadin.ui.ComboBox; import com.vaadin.ui.CustomComponent; @@ -53,6 +55,7 @@ import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.ProgressBar; import com.vaadin.ui.TextArea; +import com.vaadin.ui.UI; import com.vaadin.ui.Upload; import com.vaadin.ui.Upload.FailedEvent; import com.vaadin.ui.Upload.FailedListener; @@ -80,9 +83,7 @@ public class BulkUploadHandler extends CustomComponent private final transient DeploymentManagement deploymentManagement; private final transient DistributionSetManagement distributionSetManagement; - private final UINotification uINotification; - - protected File tempFile = null; + protected File tempFile; private Upload upload; private final ProgressBar progressBar; @@ -90,8 +91,8 @@ public class BulkUploadHandler extends CustomComponent private final TargetBulkTokenTags targetBulkTokenTags; private final Label targetsCountLabel; - private long failedTargetCount = 0; - private long successfullTargetCount = 0; + private long failedTargetCount; + private long successfullTargetCount; private final transient Executor executor; private transient EventBus.SessionEventBus eventBus; @@ -99,6 +100,7 @@ public class BulkUploadHandler extends CustomComponent final TargetBulkUpdateWindowLayout targetBulkUpdateWindowLayout; private transient EntityFactory entityFactory; + private final UI uiInstance; /** * @@ -106,20 +108,19 @@ public class BulkUploadHandler extends CustomComponent * @param targetManagement * @param managementUIState * @param deploymentManagement - * @param uINotification * @param i18n */ public BulkUploadHandler(final TargetBulkUpdateWindowLayout targetBulkUpdateWindowLayout, final TargetManagement targetManagement, final ManagementUIState managementUIState, - final DeploymentManagement deploymentManagement, final UINotification uINotification, final I18N i18n) { + final DeploymentManagement deploymentManagement, final I18N i18n, final UI uiInstance) { this.targetBulkUpdateWindowLayout = targetBulkUpdateWindowLayout; + this.uiInstance = uiInstance; this.comboBox = targetBulkUpdateWindowLayout.getDsNamecomboBox(); this.descTextArea = targetBulkUpdateWindowLayout.getDescTextArea(); this.targetManagement = targetManagement; this.progressBar = targetBulkUpdateWindowLayout.getProgressBar(); this.managementUIState = managementUIState; this.deploymentManagement = deploymentManagement; - this.uINotification = uINotification; this.targetsCountLabel = targetBulkUpdateWindowLayout.getTargetsCountLabel(); this.targetBulkTokenTags = targetBulkUpdateWindowLayout.getTargetBulkTokenTags(); this.i18n = i18n; @@ -175,6 +176,7 @@ public class BulkUploadHandler extends CustomComponent } class UploadAsync implements Runnable { + final SucceededEvent event; /** @@ -190,7 +192,6 @@ public class BulkUploadHandler extends CustomComponent if (tempFile == null) { return; } - try (InputStream tempStream = new FileInputStream(tempFile)) { readFileStream(tempStream); } catch (final FileNotFoundException e) { @@ -198,12 +199,11 @@ public class BulkUploadHandler extends CustomComponent } catch (final IOException e) { LOG.error("Error while opening temorary file ", e); } - } private void readFileStream(final InputStream tempStream) { String line; - try (BufferedReader reader = new BufferedReader( + try (final BufferedReader reader = new BufferedReader( new InputStreamReader(tempStream, Charset.defaultCharset()))) { LOG.info("Bulk file upload started"); long innerCounter = 0; @@ -219,17 +219,32 @@ public class BulkUploadHandler extends CustomComponent innerCounter++; readEachLine(line, innerCounter, totalFileSize); } - doAssignments(); - eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_UPLOAD_COMPLETED)); - // Clearing after assignments are done - managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated().clear(); } catch (final IOException e) { LOG.error("Error reading file {}", tempFile.getName(), e); + } catch (final RuntimeException e) { + uiInstance.getErrorHandler().error(new ConnectorErrorEvent(uiInstance, e)); } finally { - resetCounts(); deleteFile(); } + syncCountAfterUpload(); + doAssignments(); + eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_UPLOAD_COMPLETED)); + // Clearing after assignments are done + managementUIState.getTargetTableFilters().getBulkUpload().getTargetsCreated().clear(); + resetCounts(); + } + + private void syncCountAfterUpload() { + if (managementUIState.getTargetTableFilters().getBulkUpload() + .getSucessfulUploadCount() != successfullTargetCount) { + managementUIState.getTargetTableFilters().getBulkUpload() + .setSucessfulUploadCount(successfullTargetCount); + eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_TARGET_CREATED)); + } + if (managementUIState.getTargetTableFilters().getBulkUpload().getFailedUploadCount() != failedTargetCount) { + managementUIState.getTargetTableFilters().getBulkUpload().setSucessfulUploadCount(failedTargetCount); + } } private double getTotalNumberOfLines() { @@ -393,7 +408,7 @@ public class BulkUploadHandler extends CustomComponent } - private void setTargetValues(final Target target, final String name, final String description) { + private static void setTargetValues(final Target target, final String name, final String description) { if (null == name) { target.setName(target.getControllerId()); } else { @@ -445,11 +460,14 @@ public class BulkUploadHandler extends CustomComponent @Override public void uploadStarted(final StartedEvent event) { if (!event.getFilename().endsWith(".csv")) { - uINotification.displayError(i18n.get("bulk.targets.upload"), null, true); + + new HawkbitErrorNotificationMessage(SPUILabelDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE, null, + i18n.get("bulk.targets.upload"), true).show(Page.getCurrent()); LOG.error("Wrong file format for file {}", event.getFilename()); upload.interruptUpload(); } else { eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.BULK_TARGET_UPLOAD_STARTED)); } } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java index aa9f346a1..6c08896c1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBeanQuery.java @@ -190,9 +190,9 @@ public class TargetBeanQuery extends AbstractBeanQuery { final ManagementUIState tmpManagementUIState = getManagementUIState(); tmpManagementUIState.setTargetsCountAll(totSize); - if (size > SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { - tmpManagementUIState.setTargetsTruncated(size - SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES); - size = SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES; + if (size > SPUIDefinitions.MAX_TABLE_ENTRIES) { + tmpManagementUIState.setTargetsTruncated(size - SPUIDefinitions.MAX_TABLE_ENTRIES); + size = SPUIDefinitions.MAX_TABLE_ENTRIES; } else { tmpManagementUIState.setTargetsTruncated(null); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkTokenTags.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkTokenTags.java index 1587951dd..bbcba62ff 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkTokenTags.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkTokenTags.java @@ -96,6 +96,7 @@ public class TargetBulkTokenTags extends AbstractTargetTagToken { @Override protected void populateContainer() { container.removeAllItems(); + tagDetails.clear(); for (final TargetTag tag : tagManagement.findAllTargetTags()) { setContainerPropertValues(tag.getId(), tag.getName(), tag.getColour()); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkUpdateWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkUpdateWindowLayout.java index e806e4f30..bfc889e7f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkUpdateWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetBulkUpdateWindowLayout.java @@ -31,7 +31,6 @@ import org.eclipse.hawkbit.ui.utils.SPUIComponentIdProvider; 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.UINotification; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer; @@ -53,6 +52,7 @@ import com.vaadin.ui.Label; import com.vaadin.ui.Link; import com.vaadin.ui.ProgressBar; import com.vaadin.ui.TextArea; +import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window; import com.vaadin.ui.themes.ValoTheme; @@ -73,9 +73,6 @@ public class TargetBulkUpdateWindowLayout extends CustomComponent { @Autowired private transient TargetManagement targetManagement; - @Autowired - private transient UINotification uINotification; - @Autowired private transient EventBus.SessionEventBus eventBus; @@ -178,7 +175,7 @@ public class TargetBulkUpdateWindowLayout extends CustomComponent { private BulkUploadHandler getBulkUploadHandler() { final BulkUploadHandler bulkUploadHandler = new BulkUploadHandler(this, targetManagement, managementUIState, - deploymentManagement, uINotification, i18n); + deploymentManagement, i18n, UI.getCurrent()); bulkUploadHandler.buildLayout(); bulkUploadHandler.addStyleName(SPUIStyleDefinitions.BULK_UPLOAD_BUTTON); return bulkUploadHandler; @@ -296,8 +293,9 @@ public class TargetBulkUpdateWindowLayout extends CustomComponent { descTextArea.clear(); targetBulkTokenTags.getTokenField().clear(); targetBulkTokenTags.populateContainer(); - progressBar.setValue(0f); + progressBar.setValue(0F); progressBar.setVisible(false); + managementUIState.getTargetTableFilters().getBulkUpload().setProgressBarCurrentValue(0F); targetsCountLabel.setVisible(false); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java index ebb2ef185..f398c460c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetDetails.java @@ -107,7 +107,6 @@ public class TargetDetails extends AbstractTableDetailsLayout { return; } targetAddUpdateWindowLayout.getWindow(getSelectedBaseEntity().getControllerId()); - // targetAddUpdateWindowLayout.populateValuesOfTarget(getSelectedBaseEntity().getControllerId()); openWindow(); } @@ -229,7 +228,7 @@ public class TargetDetails extends AbstractTableDetailsLayout { * as Module (JVM|OS|AH) * @return Label as UI */ - private Label getSWModlabel(final String labelName, final SoftwareModule swModule) { + private static Label getSWModlabel(final String labelName, final SoftwareModule swModule) { return SPUIComponentProvider.createNameValueLabel(labelName + " : ", swModule.getName(), swModule.getVersion()); } @@ -253,24 +252,19 @@ public class TargetDetails extends AbstractTableDetailsLayout { return SPUIComponentIdProvider.TARGET_DETAILS_HEADER_LABEL_ID; } - @Override - protected String getShowMetadataButtonId() { - return null; - } - @Override protected Boolean isMetadataIconToBeDisplayed() { return false; } @Override - protected void showMetadata(ClickEvent event) { - //No implementation required + protected void showMetadata(final ClickEvent event) { + // No implementation required } @Override protected void populateMetadataDetails() { - //No implementation required + // No implementation required } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java index 0a70f60d5..ec0ad0c55 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTable.java @@ -17,11 +17,12 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent; import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.TargetManagement; 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.model.Target; import org.eclipse.hawkbit.repository.model.TargetIdName; import org.eclipse.hawkbit.repository.model.TargetInfo; @@ -142,6 +143,8 @@ public class TargetTable extends AbstractTable { onTargetInfoUpdateEvents((List) events); } else if (TargetDeletedEvent.class.isInstance(firstEvent)) { onTargetDeletedEvent((List) events); + } else if(TargetUpdatedEvent.class.isInstance(firstEvent)){ + onTargetUpdateEvents((List) events); } } @@ -809,7 +812,7 @@ public class TargetTable extends AbstractTable { private void refreshTargets() { final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource(); final int size = targetContainer.size(); - if (size < SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { + if (size < SPUIDefinitions.MAX_TABLE_ENTRIES) { refreshTablecontainer(); } else { // If table is not refreshed , explicitly target total count and @@ -829,10 +832,12 @@ public class TargetTable extends AbstractTable { final TargetIdName targetIdName) { final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource(); final Item item = targetContainer.getItem(targetIdName); - item.getItemProperty(SPUILabelDefinitions.VAR_TARGET_STATUS).setValue(targetInfo.getUpdateStatus()); item.getItemProperty(SPUILabelDefinitions.VAR_NAME).setValue(target.getName()); - item.getItemProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP) - .setValue(HawkbitCommonUtil.getPollStatusToolTip(targetInfo.getPollStatus(), i18n)); + if (targetInfo != null) { + item.getItemProperty(SPUILabelDefinitions.VAR_POLL_STATUS_TOOL_TIP).setValue( + HawkbitCommonUtil.getPollStatusToolTip(targetInfo.getPollStatus(), i18n)); + item.getItemProperty(SPUILabelDefinitions.VAR_TARGET_STATUS).setValue(targetInfo.getUpdateStatus()); + } } private boolean isLastSelectedTarget(final TargetIdName targetIdName) { @@ -879,6 +884,35 @@ public class TargetTable extends AbstractTable { } } + + private void onTargetUpdateEvents(List events) { + final List visibleItemIds = (List) getVisibleItemIds(); + boolean shoulTargetsUpdated = false; + Target lastSelectedTarget = null; + for (final TargetUpdatedEvent targetUpdatedEvent : events) { + Target target = targetUpdatedEvent.getEntity(); + final TargetIdName targetIdName = target.getTargetIdName(); + if (Filters.or(getTargetTableFilters(target)).doFilter()) { + shoulTargetsUpdated = true; + } else { + if (visibleItemIds.contains(targetIdName)) { + updateVisibleItemOnEvent(null, target, targetIdName); + } + } + if (isLastSelectedTarget(targetIdName)) { + lastSelectedTarget = target; + } + } + if (shoulTargetsUpdated) { + refreshTargets(); + } + if (lastSelectedTarget != null) { + eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.SELECTED_ENTITY, lastSelectedTarget)); + } + } + + + private void onTargetCreatedEvents() { refreshTargets(); } @@ -899,6 +933,7 @@ public class TargetTable extends AbstractTable { /** * Select all rows in the table. */ + @Override public void selectAll() { // As Vaadin Table only returns the current ItemIds which are visible @@ -953,8 +988,8 @@ public class TargetTable extends AbstractTable { size = getTargetsCountWithFilter(totalTargetsCount, status, targetTags, distributionId, searchText, noTagClicked, pinnedDistId); - if (size > SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { - managementUIState.setTargetsTruncated(size - SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES); + if (size > SPUIDefinitions.MAX_TABLE_ENTRIES) { + managementUIState.setTargetsTruncated(size - SPUIDefinitions.MAX_TABLE_ENTRIES); } } @@ -999,4 +1034,4 @@ public class TargetTable extends AbstractTable { private boolean isFilteredByTags() { return !managementUIState.getTargetTableFilters().getClickedTargetTags().isEmpty(); } -} \ No newline at end of file +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java index 1caafe307..defcc82c0 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java @@ -56,6 +56,11 @@ import com.vaadin.ui.themes.ValoTheme; @UIScope public final class DashboardMenu extends CustomComponent { + private static final String STYLE_VISIBLE = "valo-menu-visible"; + public static final String ID = "dashboard-menu"; + public static final String REPORTS_BADGE_ID = "dashboard-menu-reports-badge"; + public static final String NOTIFICATIONS_BADGE_ID = "dashboard-menu-notifications-badge"; + @Autowired private I18N i18n; @@ -67,11 +72,6 @@ public final class DashboardMenu extends CustomComponent { private static final long serialVersionUID = 5394474618559481462L; - public static final String ID = "dashboard-menu"; - public static final String REPORTS_BADGE_ID = "dashboard-menu-reports-badge"; - public static final String NOTIFICATIONS_BADGE_ID = "dashboard-menu-notifications-badge"; - private static final String STYLE_VISIBLE = "valo-menu-visible"; - // this should be resolved when we introduce event bus on UI to just inform // the buttons directly via events private final List menuButtons = new ArrayList<>(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java index 05eabf249..8a7d11df1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/AddUpdateRolloutWindowLayout.java @@ -44,8 +44,6 @@ 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.UINotification; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer; @@ -80,8 +78,6 @@ public class AddUpdateRolloutWindowLayout extends GridLayout { private static final long serialVersionUID = 2999293468801479916L; - private static final Logger LOG = LoggerFactory.getLogger(AddUpdateRolloutWindowLayout.class); - private static final String MESSAGE_ROLLOUT_FIELD_VALUE_RANGE = "message.rollout.field.value.range"; private static final String MESSAGE_ENTER_NUMBER = "message.enter.number"; @@ -154,6 +150,13 @@ public class AddUpdateRolloutWindowLayout extends GridLayout { buildLayout(); } + /** + * Get the window. + * + * @param rolloutId + * the rollout id + * @return the window + */ public CommonDialogWindow getWindow(final Long rolloutId) { window = getWindow(); populateData(rolloutId); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java index b58e2e7b8..9ebb1d065 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutListGrid.java @@ -443,7 +443,7 @@ public class RolloutListGrid extends AbstractGrid { return null; } - private String getDSDetails(final Item rolloutItem) { + private static String getDSDetails(final Item rolloutItem) { final StringBuilder swModuleNames = new StringBuilder(); final StringBuilder swModuleVendors = new StringBuilder(); final Set swModules = (Set) rolloutItem.getItemProperty(SW_MODULES).getValue(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java index 685be685e..487f05ae5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsBeanQuery.java @@ -140,9 +140,9 @@ public class RolloutGroupTargetsBeanQuery extends AbstractBeanQuery size = firstPageTargetSets.getTotalElements(); } getRolloutUIState().setRolloutGroupTargetsTotalCount(size); - if (size > SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { - getRolloutUIState().setRolloutGroupTargetsTruncated(size - SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES); - return SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES; + if (size > SPUIDefinitions.MAX_TABLE_ENTRIES) { + getRolloutUIState().setRolloutGroupTargetsTruncated(size - SPUIDefinitions.MAX_TABLE_ENTRIES); + return SPUIDefinitions.MAX_TABLE_ENTRIES; } return (int) size; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsCountLabelMessage.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsCountLabelMessage.java index c791a0eb2..e5c716e83 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsCountLabelMessage.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rolloutgrouptargets/RolloutGroupTargetsCountLabelMessage.java @@ -94,7 +94,7 @@ public class RolloutGroupTargetsCountLabelMessage extends Label { // set the icon setIcon(FontAwesome.INFO_CIRCLE); setDescription(i18n.get("rollout.group.label.target.truncated", - rolloutUIState.getRolloutGroupTargetsTruncated(), SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES)); + rolloutUIState.getRolloutGroupTargetsTruncated(), SPUIDefinitions.MAX_TABLE_ENTRIES)); totalTargetTableEnteries += rolloutUIState.getRolloutGroupTargetsTruncated(); } else { setIcon(null); @@ -104,9 +104,9 @@ public class RolloutGroupTargetsCountLabelMessage extends Label { final StringBuilder message = new StringBuilder(i18n.get("label.target.filter.count")); message.append(rolloutUIState.getRolloutGroupTargetsTotalCount()); message.append(HawkbitCommonUtil.SP_STRING_SPACE); - if (totalTargetTableEnteries > SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES) { + if (totalTargetTableEnteries > SPUIDefinitions.MAX_TABLE_ENTRIES) { message.append(i18n.get("label.filter.shown")); - message.append(SPUIDefinitions.MAX_TARGET_TABLE_ENTRIES); + message.append(SPUIDefinitions.MAX_TABLE_ENTRIES); } else { message.append(i18n.get("label.filter.shown")); message.append(rolloutGroupTargetsListGrid.getContainerDataSource().size()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationConfigField.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationConfigField.java index 15f51877d..9a3a54a5e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationConfigField.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/polling/DurationConfigField.java @@ -24,7 +24,7 @@ import com.vaadin.ui.GridLayout; * duration in the DurationField or he can configure using the global duration * by changing the CheckBox. */ -public class DurationConfigField extends GridLayout implements ConfigurationItem { +public final class DurationConfigField extends GridLayout implements ConfigurationItem { private static final long serialVersionUID = 1L; @@ -130,45 +130,96 @@ public class DurationConfigField extends GridLayout implements ConfigurationItem configurationChangeListeners.add(listener); } + /** + * Create a DurationConfigFieldBuilder. + * + * @return the builder + */ public static DurationConfigFieldBuilder builder() { return new DurationConfigFieldBuilder(); } - public static class DurationConfigFieldBuilder { + /** + * Builder for the calendar widget. + * + */ + public static final class DurationConfigFieldBuilder { private final DurationConfigField field; - private Duration globalDuration = null; - private Duration tenantDuration = null; + private Duration globalDuration; + private Duration tenantDuration; private DurationConfigFieldBuilder() { field = new DurationConfigField(); - }; + } + /** + * set the checkbox tooltip. + * + * @param label + * the tooltip + * @return the builder + */ public DurationConfigFieldBuilder checkBoxTooltip(final String label) { field.setCheckBoxTooltip(label); return this; } + /** + * set the global duration. + * + * @param globalDuration + * the global duration + * @return the builder + */ public DurationConfigFieldBuilder globalDuration(final Duration globalDuration) { this.globalDuration = globalDuration; return this; } + /** + * set the caption. + * + * @param caption + * the caption + * @return the builder + */ public DurationConfigFieldBuilder caption(final String caption) { field.setCaption(caption); return this; } + /** + * set the range. + * + * @param minDuration + * min duration + * @param maxDuration + * max duration + * @return the builder + */ public DurationConfigFieldBuilder range(final Duration minDuration, final Duration maxDuration) { field.setAllowedRange(minDuration, maxDuration); return this; } + /** + * set the tenant duration. + * + * @param tenantDuration + * the duration + * @return the builder + */ public DurationConfigFieldBuilder tenantDuration(final Duration tenantDuration) { this.tenantDuration = tenantDuration; return this; } + /** + * Create the {@link DurationConfigField}. + * + * @return the {@link DurationConfigField} + */ public DurationConfigField build() { if (globalDuration == null) { throw new IllegalStateException( @@ -178,5 +229,5 @@ public class DurationConfigField extends GridLayout implements ConfigurationItem field.init(globalDuration, tenantDuration); return field; } - }; + } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java index 217a84a30..b5ac26d11 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/HawkbitCommonUtil.java @@ -590,24 +590,6 @@ public final class HawkbitCommonUtil { return requiredExtraWidth + minTableWidth; } - /** - * get the Last sequence of string which is after last dot in String. - * - * @param name - * dotted String name - * @return String name - */ - public static String getLastSequenceBySplitByDot(final String name) { - String lastSequence = null; - if (null != name) { - final String[] strArray = name.split("\\."); - if (strArray.length > 0) { - lastSequence = strArray[strArray.length - 1]; - } - } - return lastSequence; - } - /** * Remove the prefix from text. * diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java index edfb99f22..1e2dbcf07 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/NotificationMessage.java @@ -16,8 +16,6 @@ import com.vaadin.ui.Notification; /** * Show notification messages. - * - * */ @UIScope @SpringComponent @@ -27,8 +25,6 @@ public class NotificationMessage extends Notification { /** * Default constructor of notification message. - * - * @param caption */ public NotificationMessage() { super(""); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java index 2ee565bb1..5d1248681 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIDefinitions.java @@ -273,10 +273,6 @@ public final class SPUIDefinitions { * New Target save icon id. */ public static final String NEW_TARGET_SAVE = "target.add.save"; - /** - * New Target discard icon id. - */ - // public static final String NEW_TARGET_DISCARD = "target.add.discard"; /** * New Target add icon id. */ @@ -309,6 +305,11 @@ public final class SPUIDefinitions { * New Create Update option group id. */ public static final String CREATE_OPTION_GROUP_DISTRIBUTION_SET_TYPE_ID = "create.option.group.dist.set.type.id"; + + /** + * Assign option group id(Firmware/Software). + */ + public static final String ASSIGN_OPTION_GROUP_SOFTWARE_MODULE_TYPE_ID = "assign.option.group.soft.module.type.id"; /** * SW Module Source Table ID. */ @@ -856,7 +857,7 @@ public final class SPUIDefinitions { * truncates it. This protects to endless scroll to very high page numbers * which is very in performant. */ - public static final int MAX_TARGET_TABLE_ENTRIES = 5000; + public static final int MAX_TABLE_ENTRIES = 5000; /** * New software module set type add icon id. diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUILabelDefinitions.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUILabelDefinitions.java index d930b89ea..22d680872 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUILabelDefinitions.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUILabelDefinitions.java @@ -54,6 +54,7 @@ public final class SPUILabelDefinitions { */ public static final String SP_NOTIFICATION_ERROR_MESSAGE_STYLE = ValoTheme.NOTIFICATION_ERROR + " " + ValoTheme.NOTIFICATION_TRAY; + /** * Style - Warning. */ @@ -539,13 +540,12 @@ public final class SPUILabelDefinitions { * Total target coulmn property name. */ public static final String VAR_TOTAL_TARGETS = "totalTargetsCount"; - - + /** * Total target count status coulmn property name. */ public static final String VAR_TOTAL_TARGETS_COUNT_STATUS = "totalTargetCountStatus"; - + /** * Rollout group started date column property. */ @@ -560,7 +560,7 @@ public final class SPUILabelDefinitions { * Rollout group installed percentage column property. */ public static final String ROLLOUT_GROUP_INSTALLED_PERCENTAGE = "finishedPercentage"; - + /** * Add metadata icon. */ diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java index a1982d625..8e7c52bc6 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UINotification.java @@ -18,8 +18,6 @@ import com.vaadin.spring.annotation.ViewScope; /** * Show success and error messages. - * - * */ @ViewScope @SpringComponent @@ -33,8 +31,6 @@ public class UINotification implements Serializable { /** * Display success type of notification message. * - * @param notificationMessage - * as reference * @param message * is the message to displayed as success. */ @@ -46,8 +42,6 @@ public class UINotification implements Serializable { /** * Display error type of notification message. * - * @param notificationMessage - * as reference * @param message * as message. */ @@ -59,18 +53,4 @@ public class UINotification implements Serializable { updatedMsg.toString(), true); } - /** - * Display error type of notification message. - * - * @param message. - * @param caption. - * @param autoClose. - */ - public void displayError(final String message, final String caption, final Boolean autoClose) { - final StringBuilder updatedMsg = new StringBuilder(FontAwesome.EXCLAMATION_TRIANGLE.getHtml()); - updatedMsg.append(' '); - updatedMsg.append(message); - notificationMessage.showNotification(SPUILabelDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE, caption, - updatedMsg.toString(), autoClose); - } } diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index 383341f4f..bb399ddf1 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -386,6 +386,7 @@ message.metadata.updated = Metadata with key {0} successfully updated ! message.metadata.duplicate.check = Metadata with key {0} already exists, please enter another value message.metadata.deleted.successfully = Metadata with key {0} successfully deleted ! message.confirm.delete.metadata = Are you sure that you want to delete metadata with key {0} ? +message.error.notification.ds.target.assigned = Distribution set {0}:{1} is already assigned to targets and cannot be changed # Login view notification.login.title=Welcome to Bosch IoT Software Provisioning. diff --git a/hawkbit-ui/src/main/resources/messages_de.properties b/hawkbit-ui/src/main/resources/messages_de.properties index cec24e1d8..fa62091fd 100644 --- a/hawkbit-ui/src/main/resources/messages_de.properties +++ b/hawkbit-ui/src/main/resources/messages_de.properties @@ -375,6 +375,7 @@ message.metadata.updated = Metadata with key {0} successfully updated ! message.metadata.duplicate.check = Metadata with key {0} already exists, please enter another value message.metadata.deleted.successfully = Metadata with key {0} successfully deleted ! message.confirm.delete.metadata = Are you sure that you want to delete metadata with key {0} ? +message.error.notification.ds.target.assigned = Distribution set {0}:{1} is already assigned to targets and cannot be changed # Login view diff --git a/hawkbit-ui/src/main/resources/messages_en.properties b/hawkbit-ui/src/main/resources/messages_en.properties index dbb2b5c6f..65e63c228 100644 --- a/hawkbit-ui/src/main/resources/messages_en.properties +++ b/hawkbit-ui/src/main/resources/messages_en.properties @@ -371,6 +371,7 @@ message.metadata.updated = Metadata with key {0} successfully updated ! message.metadata.duplicate.check = Metadata with key {0} already exists, please enter another value message.metadata.deleted.successfully = Metadata with key {0} successfully deleted ! message.confirm.delete.metadata = Are you sure that you want to delete metadata with key {0} ? +message.error.notification.ds.target.assigned = Distribution set {0}:{1} is already assigned to targets and cannot be changed # Login view notification.login.title=Welcome to Bosch IoT Software Provisioning. diff --git a/pom.xml b/pom.xml index 5c4c4bd57..0f4270afc 100644 --- a/pom.xml +++ b/pom.xml @@ -97,7 +97,6 @@ 1.5.4 1.0.2 0.9.1 - 1.8.5 19.0 1.4.3 1.50.5 @@ -120,33 +119,13 @@ https://sonar.eu-gb.mybluemix.net eclipse/hawkbit - jacoco https://projects.eclipse.org/projects/iot.hawkbit https://circleci.com/gh/eclipse/hawkbit - 0.7.7.201606060606 - - 1.4 - - reuseReports - ${project.basedir}/../target/ - jacoco-ut.exec - ${jacoco.outputDir}/${jacoco.out.ut.file} - jacoco-it.exec - ${jacoco.outputDir}/${jacoco.out.it.file} @@ -291,7 +270,6 @@ 1 ${jacoco.agent.ut.arg} - -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" @@ -308,13 +286,6 @@ **/Abstract*.java - - - org.aspectj - aspectjweaver - ${aspectj.version} - - org.apache.maven.plugins @@ -322,8 +293,7 @@ true 3 - -Xmx1024m ${jacoco.agent.ut.arg} - -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" + -Xmx1024m ${jacoco.agent.ut.arg} listener @@ -331,13 +301,6 @@ - - - org.aspectj - aspectjweaver - ${aspectj.version} - - integration-test