From 1eedd3a531f2f541a51574c5725996cfd93cd1d0 Mon Sep 17 00:00:00 2001 From: Fabian Nonnenmacher Date: Thu, 14 Jan 2016 13:08:50 +0100 Subject: [PATCH] Implemented Buisnesslogic to read and save correct polling configuration - added min and max values to config files - updated ControllerPollProperties: added getter and setter of min and max values - updated PollConfigurationHelper: added getter for different values Signed-off-by: Nonnenmacher Fabian --- .../main/resources/hawkbitdefaults.properties | 4 + .../hawkbit/ControllerPollProperties.java | 18 + .../model/helper/PollConfigurationHelper.java | 368 +++++++++++++----- 3 files changed, 288 insertions(+), 102 deletions(-) diff --git a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties index 98749a384..d3ddb6483 100644 --- a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties +++ b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties @@ -48,6 +48,10 @@ hawkbit.threadpool.queuesize=20000 # Defines the polling time for the controllers in HH:MM:SS notation hawkbit.controller.pollingTime=00:05:00 hawkbit.controller.pollingOverdueTime=00:05:00 +hawkbit.controller.maxPollingTime=23:59:59 +hawkbit.controller.minPollingTime=00:00:30 +# Attention: if you want to use a maximumPollingTime greater 23:59:59 you have to update the DurationField in the configuration window + ## Configuration for RabbitMQ integration hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java index 7c33301f3..1c19b35d0 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java @@ -20,6 +20,8 @@ public class ControllerPollProperties { private String pollingTime = "00:05:00"; private String pollingOverdueTime = "00:05:00"; + private String maxPollingTime = "23:59:00"; + private String minPollingTime = "23:59:00"; public String getPollingTime() { return pollingTime; @@ -36,4 +38,20 @@ public class ControllerPollProperties { public void setPollingOverdueTime(final String pollingOverdue) { this.pollingOverdueTime = pollingOverdue; } + + public String getMaxPollingTime() { + return maxPollingTime; + } + + public void setMaxPollingTime(String maxPollingTime) { + this.maxPollingTime = maxPollingTime; + } + + public String getMinPollingTime() { + return minPollingTime; + } + + public void setMinPollingTime(String minPollingTime) { + this.minPollingTime = minPollingTime; + } } diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/helper/PollConfigurationHelper.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/helper/PollConfigurationHelper.java index 48a55f9b0..9b9d24de9 100644 --- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/helper/PollConfigurationHelper.java +++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/model/helper/PollConfigurationHelper.java @@ -9,8 +9,13 @@ package org.eclipse.hawkbit.repository.model.helper; import java.time.Duration; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAccessor; import javax.annotation.PostConstruct; +import javax.validation.constraints.NotNull; import org.eclipse.hawkbit.ControllerPollProperties; import org.eclipse.hawkbit.repository.SystemManagement; @@ -26,17 +31,14 @@ import org.springframework.context.EnvironmentAware; * configuration in beans not instatinated by spring e.g. JPA entities which * cannot implement the {@link EnvironmentAware} interface to retrieve * environment variables. - * - * - * - * */ public final class PollConfigurationHelper { /** - * Expected format of the Polling Time String + * Format of the expected Duration String. Pattern has to be in Valid Format + * for SimpleDateFormat */ - public static final String EXPECTED_POLLING_TIME_FORMAT = "(([0-1]?[0-9]|2[0-3])(:[0-5][0-9]){2})"; + public static final String DURATION_FORMAT = "HH:mm:ss"; private static final Logger LOG = LoggerFactory.getLogger(PollConfigurationHelper.class); private static final PollConfigurationHelper INSTANCE = new PollConfigurationHelper(); @@ -49,71 +51,24 @@ public final class PollConfigurationHelper { private static final int DEFAULT_POLL_MINUTE = 5; private static final int DEFAULT_POLL_SECOND = 0; + private static final int DEFAULT_MAX_HOUR = 23; + private static final int DEFAULT_MAX_MINUTE = 59; + private static final int DEFAULT_MAX_SECOND = 59; + + private static final int DEFAULT_MIN_HOUR = 0; + private static final int DEFAULT_MIN_MINUTE = 0; + private static final int DEFAULT_MIN_SECOND = 30; + @Autowired private ControllerPollProperties controllerPollProperties; @Autowired private SystemManagement systemManagement; - private Duration controllerPollTimeDuration; - private Duration controllerOverduePollTimeDuration; - - private PollConfigurationHelper() { - } - - /** - * Bean post construct to calculate the poll time and poll overdue time only - * once. - */ - @PostConstruct - public void postConstruct() { - final long[] controllerPollTimeSplit = splitInterval(controllerPollProperties.getPollingTime(), - DEFAULT_POLL_HOUR, DEFAULT_POLL_MINUTE, DEFAULT_POLL_SECOND); - this.controllerPollTimeDuration = Duration.ZERO.plusHours(controllerPollTimeSplit[0]) - .plusMinutes(controllerPollTimeSplit[1]).plusSeconds(controllerPollTimeSplit[2]); - - final long[] controllerOverduePollTimeSplit = splitInterval(controllerPollProperties.getPollingOverdueTime(), - DEFAULT_OVERDUE_HOUR, DEFAULT_OVERDUE_MINUTE, DEFAULT_OVERDUE_SECOND); - this.controllerOverduePollTimeDuration = Duration.ZERO.plusHours(controllerOverduePollTimeSplit[0]) - .plusMinutes(controllerOverduePollTimeSplit[1]).plusSeconds(controllerOverduePollTimeSplit[2]); - } - - /** - * @return the poll time interval configured in the configuration - * {@code hawkbit.server.controller.polling} or the default value - * which is {@code 00:05:00} never {@code null}. - */ - public Duration getPollTimeInterval() { - return controllerPollTimeDuration; - } - - /** - * @return the poll time interval configured in the configuration - * {@code hawkbit.server.controller.polling} or the default value - * which is {@code 00:05:00} never {@code null}. - */ - public String getPollTimeIntervalAsFormattedString() { - return durationToFormattedString(controllerPollTimeDuration); - } - - /** - * @return the overdue poll threshold configured in the configuration - * {@code hawkbit.server.controller.polling.overdue} or the default - * value which is {@code 00:05:00} never {@code null}. - */ - public Duration getOverduePollTimeInterval() { - return controllerOverduePollTimeDuration; - } - - /** - * @return the overdue poll threshold as a formatted string (HH:MM:SS) - * configured in the configuration - * {@code hawkbit.server.controller.polling.overdue} or the default - * value which is {@code 00:05:00} never {@code null}. - */ - public String getOverduePollTimeIntervalAsFormattedString() { - return durationToFormattedString(controllerOverduePollTimeDuration); - } + private Duration configurationPollTime; + private Duration configurationOverduePollTime; + private Duration configurationMaximumPollTime; + private Duration configurationMinimumPollTime; /** * @return a singleton instance of the environment helper. @@ -122,53 +77,262 @@ public final class PollConfigurationHelper { return INSTANCE; } - private long[] splitInterval(final String interval, final long defaultHour, final long defaultMinute, - final long defaultSecond) { - if (interval != null) { - final String[] split = interval.split(":"); - if (split.length == 3) { - try { - return new long[] { Long.parseLong(split[0]), Long.parseLong(split[1]), Long.parseLong(split[2]) }; - } catch (final NumberFormatException e) { - LOG.warn("Cannot parse the given poll configuration {}", interval); - } - } - } - LOG.warn("Using default configuration hour:{} min:{}, second:{}", defaultHour, defaultMinute, defaultSecond); - return new long[] { defaultHour, defaultMinute, defaultSecond }; + /** + * Bean post construct to calculate the poll time and poll overdue time only + * once. + */ + @PostConstruct + public void initializeConfigurationValues() { + + readGlobalDurationsFromConfiguration(); + + validateGlobalDurations(); } - private String durationToFormattedString(Duration duration) { - long seconds = duration.getSeconds(); - long minuts = seconds / 60; - long hours = minuts / 60; + private void readGlobalDurationsFromConfiguration() { + try { + configurationMaximumPollTime = formattedStringToDuration(controllerPollProperties.getMaxPollingTime()); + } catch (DateTimeParseException e) { + // Set to default values + configurationMaximumPollTime = getDurationByTimeValues(DEFAULT_MAX_HOUR, DEFAULT_MAX_MINUTE, + DEFAULT_MAX_SECOND); + } - seconds = seconds % 60; - minuts = minuts % 60; - hours = hours % 100; + try { + configurationMinimumPollTime = formattedStringToDuration(controllerPollProperties.getMinPollingTime()); + } catch (DateTimeParseException e) { + // Set to default values + configurationMinimumPollTime = getDurationByTimeValues(DEFAULT_MIN_HOUR, DEFAULT_MIN_MINUTE, + DEFAULT_MIN_SECOND); + } + + try { + configurationPollTime = formattedStringToDuration(controllerPollProperties.getPollingTime()); + } catch (DateTimeParseException e) { + configurationPollTime = getDurationByTimeValues(DEFAULT_POLL_HOUR, DEFAULT_POLL_MINUTE, + DEFAULT_POLL_SECOND); + } + + try { + configurationOverduePollTime = formattedStringToDuration(controllerPollProperties.getPollingOverdueTime()); + } catch (DateTimeParseException e) { + configurationOverduePollTime = getDurationByTimeValues(DEFAULT_OVERDUE_HOUR, DEFAULT_OVERDUE_MINUTE, + DEFAULT_OVERDUE_SECOND); + } - return String.format("%02d:%02d:%02d", hours, minuts, seconds); } - private Duration formattedStringToDuration(String formattedDuration) { - if (formattedDuration == null || !formattedDuration.matches(EXPECTED_POLLING_TIME_FORMAT)) { - LOG.warn("Cannot parse the given poll configuration {}", formattedDuration); - throw new IllegalArgumentException( - "String is not in the EXPECTED_POLLING_TIME_FORMAT. Parsing not possible."); + private void validateGlobalDurations() { + + if (configurationMaximumPollTime.compareTo(configurationMinimumPollTime) < 0) { + // min value > max value -> use default values for both durations + LOG.warn("The configured maximum value of the polling time is smaller" + + " than the configured minimum value. Both are replaced by default values."); + + configurationMaximumPollTime = getDurationByTimeValues(DEFAULT_MAX_HOUR, DEFAULT_MAX_MINUTE, + DEFAULT_MAX_SECOND); + configurationMinimumPollTime = getDurationByTimeValues(DEFAULT_MIN_HOUR, DEFAULT_MIN_MINUTE, + DEFAULT_MIN_SECOND); } - final String[] split = formattedDuration.split(":"); - if (split.length == 3) { - try { - return Duration.ofHours(Long.parseLong(split[0])).plusMinutes(Long.parseLong(split[1])) - .plusSeconds(Long.parseLong(split[2])); - } catch (final NumberFormatException e) { - LOG.warn("Cannot parse the given poll configuration {}", formattedDuration); + if (!isWithinRange(configurationPollTime)) { + // poll time value not within allowed range ==> use default value + configurationPollTime = getDurationByTimeValues(DEFAULT_POLL_HOUR, DEFAULT_POLL_MINUTE, + DEFAULT_POLL_SECOND); + } + + if (!isWithinRange(configurationOverduePollTime)) { + // overdue poll time value not within range => use default value + configurationOverduePollTime = getDurationByTimeValues(DEFAULT_OVERDUE_HOUR, DEFAULT_OVERDUE_MINUTE, + DEFAULT_OVERDUE_SECOND); + } + } + + private boolean isWithinRange(@NotNull Duration duration) { + + return duration.compareTo(configurationMinimumPollTime) > 0 + && duration.compareTo(configurationMaximumPollTime) < 0; + } + + /** + * @return the poll time interval stored in the tenant meta data. If there + * is no tenant specific configuration the global value, configured + * in the configuration {@code hawkbit.server.controller.polling} or + * the default value which is {@code 00:05:00} never {@code null}. + */ + public Duration getPollTimeInterval() { + Duration tenantPollTimeInterval = getTenantPollTimeIntervall(); + + if (tenantPollTimeInterval != null) { + return tenantPollTimeInterval; + } + return configurationPollTime; + } + + /** + * @return the poll time interval stored in the tenant meta data. If there + * is no value stored this function returns {@code null} + */ + public Duration getTenantPollTimeIntervall() { + String tenantPollingTime = systemManagement.getTenantMetadata().getPollingTime(); + + return validateDurationStringAndGetDuration(tenantPollingTime, "polling time"); + } + + /** + * @return the poll time interval configured in the configuration + * {@code hawkbit.server.controller.polling} or the default value + * which is {@code 00:05:00} never {@code null}. This method ignores + * eventual tenant specific configurations. + */ + public Duration getGlobalPollTimeInterval() { + return configurationPollTime; + } + + /** + * Stores the changed value in the tenant meta data configuration. The value + * {@code null} is clearly allowed. Setting the poll time to {@code null} + * means no specific tenant configuration and global configuration are used. + * + * @param pollingTime + * polling time interval as formatted string {@code HH:mm:ss} or + * {@code null} + */ + public void setTenantPollTimeIntervall(Duration pollingTime) { + if (pollingTime == null) { + systemManagement.getTenantMetadata().setPollingTime(null); + return; + } + systemManagement.getTenantMetadata().setPollingTime(durationToFormattedString(pollingTime)); + } + + /** + * @return the overdue poll time interval stored in the tenant meta data. If + * there is no tenant specific configuration the global value, + * configured in the configuration + * {@code hawkbit.server.controller.polling} or the default value + * which is {@code 00:05:00} never {@code null}. + */ + public Duration getOverduePollTimeInterval() { + Duration tenantOverduePollTimeInterval = getTenantOverduePollTimeIntervall(); + + if (tenantOverduePollTimeInterval != null) { + return tenantOverduePollTimeInterval; + } + return configurationOverduePollTime; + }; + + /** + * @return the poll time interval stored in the tenant meta data. If there + * is no value stored this function returns {@code null} + */ + public Duration getTenantOverduePollTimeIntervall() { + String tenantOverduePollingTime = systemManagement.getTenantMetadata().getPollingOverdueTime(); + + return validateDurationStringAndGetDuration(tenantOverduePollingTime, "overdue polling time"); + } + + private Duration validateDurationStringAndGetDuration(String pollingTime, String paramNameForLog) { + if (pollingTime == null) { + return null; + } + + try { + Duration d = formattedStringToDuration(pollingTime); + + if (isWithinRange(d)) { + return d; } + + LOG.warn("Tenant {} has stored a {} {} which is not in the allowed range.", + systemManagement.currentTenant(), paramNameForLog, pollingTime); + + } catch (DateTimeParseException ex) { + LOG.warn("Tenant {} has stored an invalid {} {} in its meta data.", systemManagement.currentTenant(), + paramNameForLog, pollingTime); + } + return null; + } + + /** + * @return the overdue poll time interval configured in the configuration + * {@code hawkbit.server.controller.polling.overdue} or the default + * value which is {@code 00:05:00} never {@code null}. + */ + public Duration getGlobalOverduePollTimeInterval() { + return configurationOverduePollTime; + } + + /** + * Stores the polling overtime interval value in the tenant meta data + * configuration. The value {@code null} is clearly allowed. Setting the + * overdue poll time to {@code null} means no specific tenant configuration + * and global configuration are used. + * + * @param pollingTime + * polling time interval as formatted string {@code HH:mm:ss} or + * {@code null} + */ + public void setTenantOverduePollTimeIntervall(Duration pollingTime) { + if (pollingTime == null) { + systemManagement.getTenantMetadata().setPollingOverdueTime(null); + return; } - LOG.error("Cannot parse the given poll String {}, even it matches the regex \"{}\".", formattedDuration, - EXPECTED_POLLING_TIME_FORMAT); - throw new IllegalArgumentException("String is in the expected format. But parsing is not possible anyway."); + systemManagement.getTenantMetadata().setPollingOverdueTime(durationToFormattedString(pollingTime)); + } + + /** + * @return the maximum poll time duration configured in the configuration + * {@code hawkbit.server.controller.polling.overdue} or the default + * value which is {@code 23:59:00} never {@code null}. + */ + public Duration getMaximumPollingInterval() { + return configurationMaximumPollTime; + } + + /** + * @return the minimum poll time duration configured in the configuration + * {@code hawkbit.server.controller.polling.overdue} or the default + * value which is {@code 23:59:00} never {@code null}. + */ + public Duration getMinimumPollingInterval() { + return configurationMinimumPollTime; + } + + private String durationToFormattedString(@NotNull Duration duration) { + return LocalTime.ofNanoOfDay(duration.toNanos()).format(DateTimeFormatter.ofPattern(DURATION_FORMAT)); + } + + private Duration formattedStringToDuration(String formattedDuration) throws DateTimeParseException { + final TemporalAccessor ta = DateTimeFormatter.ofPattern(DURATION_FORMAT).parse(formattedDuration.trim()); + return Duration.between(LocalTime.MIDNIGHT, LocalTime.from(ta)); + } + + private Duration getDurationByTimeValues(long hours, long minutes, long seconds) { + return Duration.ofHours(hours).plusMinutes(minutes).plusSeconds(seconds); + } + + /** + * sets the ControllerPollProperties in a not spring handled context. Don't + * forget to call {@code initializeConfigurationValues} afterwards to read + * the values from the PollProperties. + * + * @param controllerPollProperties + * the controll properties + */ + public void setControllerPollProperties(ControllerPollProperties controllerPollProperties) { + this.controllerPollProperties = controllerPollProperties; + } + + /** + * sets the SystemManagement instance which is responsible for tenant + * specific configuration. + * + * @param systemManagement + * the SystemManagemnt instance + */ + public void setSystemManagement(SystemManagement systemManagement) { + this.systemManagement = systemManagement; } }