From 5fd7f3a5b38b4981d7d5c17ed49ae8c673772787 Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Thu, 21 Apr 2016 14:50:48 +0200 Subject: [PATCH 01/46] Small UI inconsitencies and glitches cleanup - Consitent table muliselect Signed-off-by: Melanie Retter --- .../artifacts/event/SoftwareModuleEvent.java | 4 ++ .../event/SoftwareModuleTypeEvent.java | 2 +- .../smtable/SoftwareModuleTable.java | 12 ++++ .../smtable/SoftwareModuleTableLayout.java | 43 ++++++++++++- .../filterlayout/AbstractFilterButtons.java | 50 ++++++++++++++-- .../table/AbstractNamedVersionTable.java | 42 ++++++++++++- .../ui/common/table/AbstractTable.java | 1 + .../ui/common/table/AbstractTableLayout.java | 20 ++++++- .../dstable/DistributionSetTable.java | 14 +++++ .../dstable/DistributionSetTableLayout.java | 43 +++++++++++++ .../event/DistributionSetTableEvent.java | 60 +++++++++++++++++++ .../event/DistributionSetTypeEvent.java | 15 +---- .../event/SoftwareModuleTableEvent.java | 51 ++++++++++++++++ .../distributions/smtable/SwModuleTable.java | 17 +++++- .../smtable/SwModuleTableLayout.java | 42 +++++++++++++ .../management/dstable/DistributionTable.java | 8 +++ .../dstable/DistributionTableLayout.java | 41 +++++++++++++ .../event/DistributionTableEvent.java | 18 ++++++ .../management/targettable/TargetTable.java | 31 ++++++---- 19 files changed, 477 insertions(+), 37 deletions(-) create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java index 95770cb8f..1764f8998 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java @@ -28,6 +28,10 @@ public class SoftwareModuleEvent extends BaseEntityEvent { private SoftwareModuleEventType softwareModuleEventType; + public SoftwareModuleEvent() { + super(null, null); + } + /** * Creates software module event. * diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java index 88e076775..f1b8deb72 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java @@ -25,7 +25,7 @@ public class SoftwareModuleTypeEvent { * */ public enum SoftwareModuleTypeEnum { - ADD_SOFTWARE_MODULE_TYPE, DELETE_SOFTWARE_MODULE_TYPE, UPDATE_SOFTWARE_MODULE_TYPE + ADD_SOFTWARE_MODULE_TYPE, DELETE_SOFTWARE_MODULE_TYPE, UPDATE_SOFTWARE_MODULE_TYPE, SELECT_ALL } private SoftwareModuleType softwareModuleType; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java index 478438891..11ac5e571 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java @@ -35,6 +35,7 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod; import com.vaadin.data.Container; import com.vaadin.data.Item; +import com.vaadin.event.Action; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; @@ -211,4 +212,15 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable * i is the id of the table */ -public abstract class AbstractNamedVersionTable extends AbstractTable { +public abstract class AbstractNamedVersionTable extends AbstractTable + implements Handler { private static final long serialVersionUID = 780050712209750719L; + protected ShortcutAction actionSelectAll; + + protected ShortcutAction actionUnSelectAll; + + /** + * Initialize the component. + */ + @Override + protected void init() { + super.init(); + actionSelectAll = new ShortcutAction(i18n.get("action.target.table.selectall")); + actionUnSelectAll = new ShortcutAction(i18n.get("action.target.table.clear")); + setMultiSelect(true); + setSelectable(true); + } + @Override protected List getTableVisibleColumns() { final List columnList = super.getTableVisibleColumns(); @@ -44,4 +64,24 @@ public abstract class AbstractNamedVersionTable extends Table { private static final Logger LOG = LoggerFactory.getLogger(AbstractTable.class); + // TODO MR should be private and use with getter/setter @Autowired protected transient EventBus.SessionEventBus eventBus; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java index b9fa20f03..fa847b4ba 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java @@ -9,8 +9,11 @@ package org.eclipse.hawkbit.ui.common.table; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractTableDetailsLayout; +import org.springframework.beans.factory.annotation.Autowired; +import org.vaadin.spring.events.EventBus; import com.vaadin.event.Action.Handler; +import com.vaadin.event.ShortcutAction; import com.vaadin.ui.Alignment; import com.vaadin.ui.Panel; import com.vaadin.ui.VerticalLayout; @@ -27,6 +30,15 @@ public abstract class AbstractTableLayout extends VerticalLayout { private static final long serialVersionUID = 8611248179949245460L; + /** + * action for the shortcut key ctrl + 'A'. + */ + protected static final ShortcutAction ACTION_CTRL_A = new ShortcutAction("Select All", ShortcutAction.KeyCode.A, + new int[] { ShortcutAction.ModifierKey.CTRL }); + + @Autowired + private transient EventBus.SessionEventBus eventBus; + private AbstractTableHeader tableHeader; private AbstractTable table; @@ -93,12 +105,14 @@ public abstract class AbstractTableLayout extends VerticalLayout { * @return reference of {@link Handler} to handler the short cut keys. * Default is null. */ - protected Handler getShortCutKeysHandler() { - return null; - } + protected abstract Handler getShortCutKeysHandler(); public void setShowFilterButtonVisible(final boolean visible) { tableHeader.setFilterButtonsIconVisible(visible); } + public EventBus.SessionEventBus getEventBus() { + return eventBus; + } + } 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 01c242247..56abe5d25 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 @@ -31,6 +31,8 @@ import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModule import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable; import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; +import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent; +import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent.DistributionSetComponentEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsViewAcceptCriteria; import org.eclipse.hawkbit.ui.distributions.event.DragEvent; @@ -55,6 +57,7 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod; import com.vaadin.data.Container; import com.vaadin.data.Item; +import com.vaadin.event.Action; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; @@ -472,4 +475,15 @@ public class DistributionSetTable extends AbstractNamedVersionTable { + + /** + * DistributionSet table components events. + * + */ + public enum DistributionSetComponentEvent { + SELECT_ALL + } + + private DistributionSetComponentEvent distributionSetComponentEvent; + + /** + * Constructor. + * + * @param eventType + * the event type. + * @param entity + * the entity + */ + public DistributionSetTableEvent(final BaseEntityEventType eventType, final DistributionSet entity) { + super(eventType, entity); + } + + /** + * The component event. + * + * @param DistributionSetTableEvent + * the distributionSet component event. + */ + public DistributionSetTableEvent(final DistributionSetComponentEvent distributionSetComponentEvent) { + super(null, null); + this.distributionSetComponentEvent = distributionSetComponentEvent; + } + + public DistributionSetComponentEvent getDistributionSetComponentEvent() { + return distributionSetComponentEvent; + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java index 9cbd1f1bc..798d2a43d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java @@ -30,16 +30,11 @@ public class DistributionSetTypeEvent { private final DistributionSetTypeEnum distributionSetTypeEnum; - private String distributionSetTypeName; - /** * @param distributionSetTypeEnum - * @param distributionSetTypeName */ - public DistributionSetTypeEvent(final DistributionSetTypeEnum distributionSetTypeEnum, - final String distributionSetTypeName) { + public DistributionSetTypeEvent(final DistributionSetTypeEnum distributionSetTypeEnum) { this.distributionSetTypeEnum = distributionSetTypeEnum; - this.distributionSetTypeName = distributionSetTypeName; } /** @@ -52,14 +47,6 @@ public class DistributionSetTypeEvent { this.distributionSetType = distributionSetType; } - public String getDistributionSetTypeName() { - return distributionSetTypeName; - } - - public void setDistributionSetTypeName(final String distributionSetTypeName) { - this.distributionSetTypeName = distributionSetTypeName; - } - public DistributionSetType getDistributionSetType() { return distributionSetType; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java new file mode 100644 index 000000000..d3347d52f --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java @@ -0,0 +1,51 @@ +package org.eclipse.hawkbit.ui.distributions.event; + +import org.eclipse.hawkbit.repository.model.SoftwareModule; +import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent; +import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; + +/** + * + * + * + */ +public class SoftwareModuleTableEvent extends BaseEntityEvent { + + /** + * SoftwareModule table components events. + * + */ + public enum SoftwareModuleComponentEvent { + SELECT_ALL + } + + private SoftwareModuleComponentEvent softwareModuleComponentEvent; + + /** + * Constructor. + * + * @param eventType + * the event type. + * @param entity + * the entity + */ + public SoftwareModuleTableEvent(final BaseEntityEventType eventType, final SoftwareModule entity) { + super(eventType, entity); + } + + /** + * The component event. + * + * @param SoftwareModuleComponentEvent + * the softwareModule component event. + */ + public SoftwareModuleTableEvent(final SoftwareModuleComponentEvent softwareModuleComponentEvent) { + super(null, null); + this.softwareModuleComponentEvent = softwareModuleComponentEvent; + } + + public SoftwareModuleComponentEvent getSoftwareModuleComponentEvent() { + return softwareModuleComponentEvent; + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java index eeea33723..d07111858 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTable.java @@ -26,6 +26,8 @@ import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmallNoBorder; import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsViewAcceptCriteria; import org.eclipse.hawkbit.ui.distributions.event.SaveActionWindowEvent; +import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent; +import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent.SoftwareModuleComponentEvent; import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider; @@ -42,6 +44,8 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod; import com.vaadin.data.Container; import com.vaadin.data.Item; +import com.vaadin.event.Action; +import com.vaadin.event.Action.Handler; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; @@ -62,7 +66,7 @@ import com.vaadin.ui.Window; */ @SpringComponent @ViewScope -public class SwModuleTable extends AbstractNamedVersionTable { +public class SwModuleTable extends AbstractNamedVersionTable implements Handler { private static final long serialVersionUID = 6785314784507424750L; @@ -388,4 +392,15 @@ public class SwModuleTable extends AbstractNamedVersionTable { + /** + * DistributionSet table components events. + * + */ + public enum DistributionTableComponentEvent { + SELECT_ALL + } + /** * Constructor. * @@ -31,4 +39,14 @@ public class DistributionTableEvent extends BaseEntityEvent { super(eventType, entity); } + /** + * The component event. + * + * @param DistributionSetTableEvent + * the distributionSet component event. + */ + public DistributionTableEvent(final DistributionTableComponentEvent distributionComponentEvent) { + super(null, null); + } + } 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 3b9c18952..7fb2446f0 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 @@ -21,7 +21,6 @@ import java.util.stream.Collectors; import org.eclipse.hawkbit.eventbus.event.TargetCreatedEvent; import org.eclipse.hawkbit.eventbus.event.TargetDeletedEvent; import org.eclipse.hawkbit.eventbus.event.TargetInfoUpdateEvent; -import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; import org.eclipse.hawkbit.repository.SpPermissionChecker; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.model.DistributionSetIdName; @@ -63,7 +62,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; import org.vaadin.addons.lazyquerycontainer.BeanQueryFactory; import org.vaadin.addons.lazyquerycontainer.LazyQueryContainer; import org.vaadin.addons.lazyquerycontainer.LazyQueryDefinition; @@ -353,6 +351,7 @@ public class TargetTable extends AbstractTable implements }; } + // TODO MR private void onTargetDeletedEvent(final List events) { final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource(); final List visibleItemIds = (List) getVisibleItemIds(); @@ -928,16 +927,24 @@ public class TargetTable extends AbstractTable implements * Select all rows in the table. */ public void selectAll() { - final PageRequest pageRequest = new OffsetBasedPageRequest(0, size(), - new Sort(SPUIDefinitions.TARGET_TABLE_CREATE_AT_SORT_ORDER, "createdAt")); - List targetIdList; - // is custom filter selected - if (managementUIState.getTargetTableFilters().getTargetFilterQuery().isPresent()) { - targetIdList = getTargetIdsByCustomFilters(pageRequest); - } else { - targetIdList = getTargetIdsBySimpleFilters(pageRequest); - } - setValue(targetIdList); + // final PageRequest pageRequest = new OffsetBasedPageRequest(0, size(), + // new Sort(SPUIDefinitions.TARGET_TABLE_CREATE_AT_SORT_ORDER, + // "createdAt")); + // List targetIdList; + // // is custom filter selected + // if + // (managementUIState.getTargetTableFilters().getTargetFilterQuery().isPresent()) + // { + // targetIdList = getTargetIdsByCustomFilters(pageRequest); + // } else { + // targetIdList = getTargetIdsBySimpleFilters(pageRequest); + // } + // setValue(targetIdList); + + // TODO MR + // As Vaadin Table only returns the current ItemIds which are visible + // you don't need to search explicit for them. + setValue(getItemIds()); } private List getTargetIdsBySimpleFilters(final PageRequest pageRequest) { From 1047219ad2701624e39a555e4264fbdab83d1ace Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Wed, 8 Jun 2016 13:02:29 +0200 Subject: [PATCH 02/46] STRG+A for selecting all table rows, remove contextMenu, remove empty lines Signed-off-by: Melanie Retter --- .../smtable/SoftwareModuleTable.java | 11 --- .../smtable/SoftwareModuleTableLayout.java | 3 - .../filterlayout/AbstractFilterButtons.java | 35 +------- .../table/AbstractNamedVersionTable.java | 17 +--- .../ui/common/table/AbstractTable.java | 1 - .../ui/common/table/AbstractTableHeader.java | 4 - .../ui/common/table/AbstractTableLayout.java | 4 - .../disttype/DSTypeFilterButtons.java | 3 - .../dstable/DistributionSetTable.java | 16 ---- .../dstable/DistributionSetTableLayout.java | 5 +- .../distributions/smtable/SwModuleTable.java | 17 +--- .../smtable/SwModuleTableLayout.java | 3 - .../management/dstable/DistributionTable.java | 12 +-- .../dstable/DistributionTableLayout.java | 3 - .../management/targettable/TargetTable.java | 89 +------------------ .../targettable/TargetTableHeader.java | 21 ++--- .../targettable/TargetTableLayout.java | 9 -- .../src/main/resources/messages_de.properties | 4 - 18 files changed, 18 insertions(+), 239 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java index 060aff55b..99fe185e5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTable.java @@ -35,7 +35,6 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod; import com.vaadin.data.Container; import com.vaadin.data.Item; -import com.vaadin.event.Action; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; @@ -213,14 +212,4 @@ public class SoftwareModuleTable extends AbstractNamedVersionTable * i is the id of the table */ -public abstract class AbstractNamedVersionTable extends AbstractTable - implements Handler { +public abstract class AbstractNamedVersionTable extends AbstractTable { private static final long serialVersionUID = 780050712209750719L; - protected ShortcutAction actionSelectAll; - - protected ShortcutAction actionUnSelectAll; - /** * Initialize the component. */ @Override protected void init() { super.init(); - actionSelectAll = new ShortcutAction(i18n.get("action.target.table.selectall")); - actionUnSelectAll = new ShortcutAction(i18n.get("action.target.table.clear")); setMultiSelect(true); setSelectable(true); } @@ -64,11 +54,6 @@ public abstract class AbstractNamedVersionTable extends Table { private static final Logger LOG = LoggerFactory.getLogger(AbstractTable.class); - // TODO MR should be private and use with getter/setter @Autowired protected transient EventBus.SessionEventBus eventBus; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableHeader.java index b137594f8..3a12ca23e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableHeader.java @@ -36,10 +36,6 @@ import com.vaadin.ui.VerticalLayout; /** * Parent class for table header. - * - * - * - * */ public abstract class AbstractTableHeader extends VerticalLayout { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java index fa847b4ba..9406dcb93 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java @@ -21,10 +21,6 @@ import com.vaadin.ui.themes.ValoTheme; /** * Parent class for table layout. - * - * - * - * */ public abstract class AbstractTableLayout extends VerticalLayout { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterButtons.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterButtons.java index 25e081fa0..9b819e1b4 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterButtons.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/disttype/DSTypeFilterButtons.java @@ -31,9 +31,6 @@ import com.vaadin.spring.annotation.ViewScope; /** * Distribution Set Type filter buttons. - * - * - * */ @SpringComponent @ViewScope 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 e305039fd..a52c0b683 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 @@ -30,8 +30,6 @@ import org.eclipse.hawkbit.ui.common.DistributionSetIdName; import org.eclipse.hawkbit.ui.common.table.AbstractNamedVersionTable; import org.eclipse.hawkbit.ui.common.table.AbstractTable; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent.DistributionSetComponentEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsUIEvent; import org.eclipse.hawkbit.ui.distributions.event.DistributionsViewAcceptCriteria; import org.eclipse.hawkbit.ui.distributions.event.DragEvent; @@ -56,7 +54,6 @@ import org.vaadin.spring.events.annotation.EventBusListenerMethod; import com.vaadin.data.Container; import com.vaadin.data.Item; -import com.vaadin.event.Action; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; @@ -68,7 +65,6 @@ import com.vaadin.ui.UI; /** * Distribution set table. - * */ @SpringComponent @ViewScope @@ -471,18 +467,6 @@ public class DistributionSetTable extends AbstractNamedVersionTable implements Handler { +public class SwModuleTable extends AbstractNamedVersionTable { private static final long serialVersionUID = 6785314784507424750L; @@ -392,15 +388,4 @@ public class SwModuleTable extends AbstractNamedVersionTable implements Handler { +public class TargetTable extends AbstractTable { private static final Logger LOG = LoggerFactory.getLogger(TargetTable.class); private static final String TARGET_PINNED = "targetPinned"; @@ -127,15 +119,10 @@ public class TargetTable extends AbstractTable implements private Button targetPinnedBtn; private Boolean isTargetPinned = Boolean.FALSE; - private ShortcutAction actionSelectAll; - private ShortcutAction actionUnSelectAll; @Override protected void init() { super.init(); - addActionHandler(this); - actionSelectAll = new ShortcutAction(i18n.get("action.target.table.selectall")); - actionUnSelectAll = new ShortcutAction(i18n.get("action.target.table.clear")); setItemDescriptionGenerator(new AssignInstalledDSTooltipGenerator()); } @@ -260,22 +247,6 @@ public class TargetTable extends AbstractTable implements HawkbitCommonUtil.addTargetTableContainerProperties(container); } - @Override - public Action[] getActions(final Object target, final Object sender) { - return new Action[] { actionSelectAll, actionUnSelectAll }; - } - - @Override - public void handleAction(final Action action, final Object sender, final Object target) { - if (actionSelectAll.equals(action)) { - selectAll(); - eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.SELLECT_ALL)); - } - if (actionUnSelectAll.equals(action)) { - unSelectAll(); - } - } - @Override protected void addCustomGeneratedColumns() { addGeneratedColumn(SPUIDefinitions.TARGET_STATUS_PIN_TOGGLE_ICON, @@ -354,7 +325,6 @@ public class TargetTable extends AbstractTable implements }; } - // TODO MR private void onTargetDeletedEvent(final List events) { final LazyQueryContainer targetContainer = (LazyQueryContainer) getContainerDataSource(); final List visibleItemIds = (List) getVisibleItemIds(); @@ -454,7 +424,7 @@ public class TargetTable extends AbstractTable implements pinBtn.setHeightUndefined(); pinBtn.setData(itemId); pinBtn.setId(SPUIComponentIdProvider.TARGET_PIN_ICON + "." + itemId); - pinBtn.addClickListener(event -> addPinClickListener(event)); + pinBtn.addClickListener(this::addPinClickListener); if (isPinned(((TargetIdName) itemId).getControllerId())) { pinBtn.addStyleName(TARGET_PINNED); isTargetPinned = Boolean.TRUE; @@ -931,62 +901,11 @@ public class TargetTable extends AbstractTable implements */ public void selectAll() { - // final PageRequest pageRequest = new OffsetBasedPageRequest(0, size(), - // new Sort(SPUIDefinitions.TARGET_TABLE_CREATE_AT_SORT_ORDER, - // "createdAt")); - // List targetIdList; - // // is custom filter selected - // if - // (managementUIState.getTargetTableFilters().getTargetFilterQuery().isPresent()) - // { - // targetIdList = getTargetIdsByCustomFilters(pageRequest); - // } else { - // targetIdList = getTargetIdsBySimpleFilters(pageRequest); - // } - // setValue(targetIdList); - - // TODO MR // As Vaadin Table only returns the current ItemIds which are visible // you don't need to search explicit for them. setValue(getItemIds()); } - private List getTargetIdsBySimpleFilters(final PageRequest pageRequest) { - final Long filterByDistId = managementUIState.getTargetTableFilters().getDistributionSet().isPresent() - ? managementUIState.getTargetTableFilters().getDistributionSet().get().getId() : null; - final List statusList = new ArrayList<>(); - if (isFilteredByStatus()) { - statusList.addAll(managementUIState.getTargetTableFilters().getClickedStatusTargetTags()); - } - final List tagList = new ArrayList<>(); - if (isFilteredByTags()) { - tagList.addAll(managementUIState.getTargetTableFilters().getClickedTargetTags()); - } - String searchText = managementUIState.getTargetTableFilters().getSearchText().isPresent() - ? managementUIState.getTargetTableFilters().getSearchText().get() : null; - if (!Strings.isNullOrEmpty(searchText)) { - searchText = String.format("%%%s%%", searchText); - } - final Boolean noTagSelected = managementUIState.getTargetTableFilters().isNoTagSelected(); - - final String[] tagArray = tagList.toArray(new String[tagList.size()]); - - List targetIdList; - targetIdList = targetManagement.findAllTargetIdsByFilters(pageRequest, statusList, searchText, filterByDistId, - noTagSelected, tagList.toArray(tagArray)); - Collections.reverse(targetIdList); - return targetIdList; - } - - private List getTargetIdsByCustomFilters(final PageRequest pageRequest) { - List targetIdList; - final TargetFilterQuery targetFilterQuery = managementUIState.getTargetTableFilters().getTargetFilterQuery() - .isPresent() ? managementUIState.getTargetTableFilters().getTargetFilterQuery().get() : null; - targetIdList = targetManagement.findAllTargetIdsByTargetFilterQuery(pageRequest, targetFilterQuery); - Collections.reverse(targetIdList); - return targetIdList; - } - /** * Clear all selections in the table. */ @@ -1073,10 +992,6 @@ public class TargetTable extends AbstractTable implements return targetManagement.countTargetsAll(); } - private static TargetIdName getLastSelectedItem(final Set values) { - return Iterables.getLast(values); - } - private boolean isFilteredByStatus() { return !managementUIState.getTargetTableFilters().getClickedStatusTargetTags().isEmpty(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java index b6379729b..5b0aa285a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java @@ -65,9 +65,6 @@ public class TargetTableHeader extends AbstractTableHeader { @Autowired private ManagementUIState managementUIState; - @Autowired - private transient EventBus.SessionEventBus eventBus; - @Autowired private ManagementViewAcceptCriteria managementViewAcceptCriteria; @@ -231,14 +228,14 @@ public class TargetTableHeader extends AbstractTableHeader { @Override protected void showFilterButtonsLayout() { managementUIState.setTargetTagFilterClosed(false); - eventBus.publish(this, ManagementUIEvent.SHOW_TARGET_TAG_LAYOUT); + eventbus.publish(this, ManagementUIEvent.SHOW_TARGET_TAG_LAYOUT); } @Override protected void resetSearchText() { if (managementUIState.getTargetTableFilters().getSearchText().isPresent()) { managementUIState.getTargetTableFilters().setSearchText(null); - eventBus.publish(this, TargetFilterEvent.REMOVE_FILTER_BY_TEXT); + eventbus.publish(this, TargetFilterEvent.REMOVE_FILTER_BY_TEXT); } } @@ -255,13 +252,13 @@ public class TargetTableHeader extends AbstractTableHeader { @Override public void maximizeTable() { managementUIState.setTargetTableMaximized(Boolean.TRUE); - eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.MAXIMIZED,null)); + eventbus.publish(this, new TargetTableEvent(BaseEntityEventType.MAXIMIZED,null)); } @Override public void minimizeTable() { managementUIState.setTargetTableMaximized(Boolean.FALSE); - eventBus.publish(this, new TargetTableEvent(BaseEntityEventType.MINIMIZED,null)); + eventbus.publish(this, new TargetTableEvent(BaseEntityEventType.MINIMIZED,null)); } @Override @@ -277,12 +274,12 @@ public class TargetTableHeader extends AbstractTableHeader { @Override protected void searchBy(final String newSearchText) { managementUIState.getTargetTableFilters().setSearchText(newSearchText); - eventBus.publish(this, TargetFilterEvent.FILTER_BY_TEXT); + eventbus.publish(this, TargetFilterEvent.FILTER_BY_TEXT); } @Override protected void addNewItem(final ClickEvent event) { - eventBus.publish(this, DragEvent.HIDE_DROP_HINT); + eventbus.publish(this, DragEvent.HIDE_DROP_HINT); targetAddUpdateWindow.resetComponents(); final Window addTargetWindow = targetAddUpdateWindow.getWindow(); addTargetWindow.setCaption(i18n.get("caption.add.new.target")); @@ -402,12 +399,12 @@ public class TargetTableHeader extends AbstractTableHeader { getFilterDroppedInfo().addComponent(filteredDistLabel); getFilterDroppedInfo().addComponent(filterLabelClose); getFilterDroppedInfo().setExpandRatio(filteredDistLabel, 1.0f); - eventBus.publish(this, TargetFilterEvent.FILTER_BY_DISTRIBUTION); + eventbus.publish(this, TargetFilterEvent.FILTER_BY_DISTRIBUTION); } private void closeFilterByDistribution() { - eventBus.publish(this, DragEvent.HIDE_DROP_HINT); + eventbus.publish(this, DragEvent.HIDE_DROP_HINT); /* Remove filter by distribution information. */ getFilterDroppedInfo().removeAllComponents(); getFilterDroppedInfo().setSizeUndefined(); @@ -415,7 +412,7 @@ public class TargetTableHeader extends AbstractTableHeader { managementUIState.getTargetTableFilters().setDistributionSet(null); /* Reload the table */ - eventBus.publish(this, TargetFilterEvent.REMOVE_FILTER_BY_DISTRIBUTION); + eventbus.publish(this, TargetFilterEvent.REMOVE_FILTER_BY_DISTRIBUTION); } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java index aaf5c6a9f..2bd86868c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java @@ -18,26 +18,17 @@ import org.vaadin.spring.events.EventBus; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; -import com.vaadin.event.ShortcutAction; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; /** * Target table layout. - * - * - * */ @SpringComponent @ViewScope public class TargetTableLayout extends AbstractTableLayout { private static final long serialVersionUID = 2248703121998709112L; - /** - * action for the shortcut key ctrl + 'A'. - */ - private static final ShortcutAction ACTION_CTRL_A = new ShortcutAction("Select All", ShortcutAction.KeyCode.A, - new int[] { ShortcutAction.ModifierKey.CTRL }); @Autowired private transient EventBus.SessionEventBus eventBus; diff --git a/hawkbit-ui/src/main/resources/messages_de.properties b/hawkbit-ui/src/main/resources/messages_de.properties index 1ced68c43..d48303ae2 100644 --- a/hawkbit-ui/src/main/resources/messages_de.properties +++ b/hawkbit-ui/src/main/resources/messages_de.properties @@ -299,10 +299,6 @@ message.tag.use.bulk.upload = {0} cannot be deleted .It is in use in targets bul message.bulk.upload.tag.assignment.failed = Tag {0} assignment failed as tag no longer exists message.bulk.upload.tag.assignments.failed= Few tag assignments failed as tags no longer exists -# action info -action.target.table.selectall = Select all (Ctrl+A) -action.target.table.clear = Clear selections - #reused messages soft.module.jvm =Runtime soft.module.application =Application From c2d1e37a16a00433f45e378df6936b676d78140b Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Wed, 8 Jun 2016 13:15:38 +0200 Subject: [PATCH 03/46] Add License and JavaDoc Signed-off-by: Melanie Retter --- .../event/SoftwareModuleTableEvent.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java index 70108acef..f722c3a23 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java @@ -1,3 +1,11 @@ +/** + * 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.distributions.event; import org.eclipse.hawkbit.repository.model.SoftwareModule; @@ -5,9 +13,7 @@ import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; /** - * - * - * + * Class which contains the Event when selecting all entries of a table */ public class SoftwareModuleTableEvent extends BaseEntityEvent { @@ -36,7 +42,7 @@ public class SoftwareModuleTableEvent extends BaseEntityEvent { /** * The component event. * - * @param SoftwareModuleComponentEvent + * @param softwareModuleComponentEvent * the softwareModule component event. */ public SoftwareModuleTableEvent(final SoftwareModuleComponentEvent softwareModuleComponentEvent) { From d5e591a4a6f38d73e3e1efd23714b95789227837 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Fri, 10 Jun 2016 08:37:56 +0200 Subject: [PATCH 04/46] Configurable basic scenario. Signed-off-by: Kai Zimmermann --- .../builder/DistributionSetBuilder.java | 32 +++-- .../builder/DistributionSetTypeBuilder.java | 10 +- .../builder/SoftwareModuleBuilder.java | 10 +- .../builder/SoftwareModuleTypeBuilder.java | 10 +- .../resource/builder/TargetBuilder.java | 53 +++++-- .../hawkbit/mgmt/client/Application.java | 10 +- .../client/ClientConfigurationProperties.java | 76 ++++++++++ .../scenarios/ConfigurableScenario.java | 92 ++++++++++++ .../CreateStartedRolloutExample.java | 2 +- .../GettingStartedDefaultScenario.java | 135 ------------------ .../src/main/resources/application.properties | 11 +- 11 files changed, 264 insertions(+), 177 deletions(-) create mode 100644 examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java delete mode 100644 examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/GettingStartedDefaultScenario.java diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java index 1e58b8415..a51d96d88 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetBuilder.java @@ -84,32 +84,48 @@ public class DistributionSetBuilder { * @return a single entry list of {@link MgmtDistributionSetRequestBodyPost} */ public List build() { - return Lists.newArrayList(doBuild(name)); + return Lists.newArrayList(doBuild("")); } /** * Builds a list of multiple {@link MgmtDistributionSetRequestBodyPost} to * create multiple distribution sets at once. An increasing number will be - * added to the name of the distribution set. The version and type will - * remain the same. + * used for version of the distribution set. The name and type will remain + * the same. * * @param count * the amount of distribution sets body which should be created * @return a list of {@link MgmtDistributionSetRequestBodyPost} */ public List buildAsList(final int count) { + return buildAsList(0, count); + } + + /** + * Builds a list of multiple {@link MgmtDistributionSetRequestBodyPost} to + * create multiple distribution sets at once. An increasing number will be + * used for version of the distribution set starting from given offset. The + * name and type will remain the same. + * + * @param count + * the amount of distribution sets body which should be created + * @param offset + * for for index start + * @return a list of {@link MgmtDistributionSetRequestBodyPost} + */ + public List buildAsList(final int offset, final int count) { final ArrayList bodyList = Lists.newArrayList(); - for (int index = 0; index < count; index++) { - bodyList.add(doBuild(name + index)); + for (int index = offset; index < count + offset; index++) { + bodyList.add(doBuild(String.valueOf(index))); } return bodyList; } - private MgmtDistributionSetRequestBodyPost doBuild(final String prefixName) { + private MgmtDistributionSetRequestBodyPost doBuild(final String suffix) { final MgmtDistributionSetRequestBodyPost body = new MgmtDistributionSetRequestBodyPost(); - body.setName(prefixName); - body.setVersion(version); + body.setName(name); + body.setVersion(version + suffix); body.setType(type); body.setDescription(description); body.setModules(modules); diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java index 1ce2ff270..028060f37 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/DistributionSetTypeBuilder.java @@ -101,7 +101,7 @@ public class DistributionSetTypeBuilder { * {@link MgmtDistributionSetTypeRequestBodyPost} */ public List build() { - return Lists.newArrayList(doBuild(name, key)); + return Lists.newArrayList(doBuild("")); } /** @@ -118,16 +118,16 @@ public class DistributionSetTypeBuilder { public List buildAsList(final int count) { final ArrayList bodyList = Lists.newArrayList(); for (int index = 0; index < count; index++) { - bodyList.add(doBuild(name + index, key + index)); + bodyList.add(doBuild(String.valueOf(index))); } return bodyList; } - private MgmtDistributionSetTypeRequestBodyPost doBuild(final String prefixName, final String prefixKey) { + private MgmtDistributionSetTypeRequestBodyPost doBuild(final String suffix) { final MgmtDistributionSetTypeRequestBodyPost body = new MgmtDistributionSetTypeRequestBodyPost(); - body.setKey(prefixKey); - body.setName(prefixName); + body.setKey(key + suffix); + body.setName(name + suffix); body.setDescription(description); body.setMandatorymodules(mandatorymodules); body.setOptionalmodules(optionalmodules); diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java index b2e544f88..1d633e440 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java @@ -96,7 +96,7 @@ public class SoftwareModuleBuilder { /** * Builds a list of multiple {@link MgmtSoftwareModuleRequestBodyPost} to * create multiple software module at once. An increasing number will be - * added to the name of the software module. The version and type will + * added to the version of the software module. The name and type will * remain the same. * * @param count @@ -106,16 +106,16 @@ public class SoftwareModuleBuilder { public List buildAsList(final int count) { final ArrayList bodyList = Lists.newArrayList(); for (int index = 0; index < count; index++) { - bodyList.add(doBuild(name + index)); + bodyList.add(doBuild(String.valueOf(index))); } return bodyList; } - private MgmtSoftwareModuleRequestBodyPost doBuild(final String prefixName) { + private MgmtSoftwareModuleRequestBodyPost doBuild(final String suffix) { final MgmtSoftwareModuleRequestBodyPost body = new MgmtSoftwareModuleRequestBodyPost(); - body.setName(prefixName); - body.setVersion(version); + body.setName(name); + body.setVersion(version + suffix); body.setType(type); body.setVendor(vendor); body.setDescription(description); diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java index 7981e61cf..7807d0f11 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleTypeBuilder.java @@ -69,7 +69,7 @@ public class SoftwareModuleTypeBuilder { * {@link MgmtSoftwareModuleTypeRequestBodyPost} */ public List build() { - return Lists.newArrayList(doBuild(key, name)); + return Lists.newArrayList(doBuild("")); } /** @@ -85,15 +85,15 @@ public class SoftwareModuleTypeBuilder { public List buildAsList(final int count) { final ArrayList bodyList = Lists.newArrayList(); for (int index = 0; index < count; index++) { - bodyList.add(doBuild(key + index, name + index)); + bodyList.add(doBuild(String.valueOf(index))); } return bodyList; } - private MgmtSoftwareModuleTypeRequestBodyPost doBuild(final String prefixKey, final String prefixName) { + private MgmtSoftwareModuleTypeRequestBodyPost doBuild(final String suffix) { final MgmtSoftwareModuleTypeRequestBodyPost body = new MgmtSoftwareModuleTypeRequestBodyPost(); - body.setKey(prefixKey); - body.setName(prefixName); + body.setKey(key + suffix); + body.setName(name + suffix); body.setDescription(description); body.setMaxAssignments(maxAssignments); return body; diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java index 7bcc0af09..de81f5354 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java @@ -8,7 +8,6 @@ */ package org.eclipse.hawkbit.mgmt.client.resource.builder; -import java.util.ArrayList; import java.util.List; import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeRequestBodyPost; @@ -65,32 +64,62 @@ public class TargetBuilder { * * @return a single entry list of {@link MgmtTargetRequestBody} */ - public List build() { - return Lists.newArrayList(doBuild(controllerId)); + public List buildAsList() { + return Lists.newArrayList(doBuild("")); + } + + /** + * Builds a single {@link MgmtTargetRequestBody}. + * + * @return build {@link MgmtTargetRequestBody} + */ + public MgmtTargetRequestBody build() { + return doBuild(""); } /** * Builds a list of multiple {@link MgmtTargetRequestBody} to create * multiple targets at once. An increasing number will be added to the - * controllerId of the target. The name and description will remain. + * controllerId and name of the target. The description will remain. * * @param count - * the amount of software module type bodies which should be - * created + * the amount of target bodies which should be created + * @param offset + * for * @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost} */ public List buildAsList(final int count) { - final ArrayList bodyList = Lists.newArrayList(); - for (int index = 0; index < count; index++) { - bodyList.add(doBuild(controllerId + index)); + + return buildAsList(0, count); + } + + /** + * Builds a list of multiple {@link MgmtTargetRequestBody} to create + * multiple targets at once. An increasing number will be added to the + * controllerId and name of the target starting from the provided offset. + * The description will remain. + * + * @param count + * the amount of target bodies which should be created + * @param offset + * for for index start + * @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost} + */ + public List buildAsList(final int offset, final int count) { + final List bodyList = Lists.newArrayList(); + for (int index = offset; index < count + offset; index++) { + bodyList.add(doBuild(String.valueOf(index))); } return bodyList; } - private MgmtTargetRequestBody doBuild(final String prefixControllerId) { + private MgmtTargetRequestBody doBuild(final String suffix) { final MgmtTargetRequestBody body = new MgmtTargetRequestBody(); - body.setControllerId(prefixControllerId); - body.setName(name); + body.setControllerId(controllerId + suffix); + if (name == null) { + name = controllerId; + } + body.setName(name + suffix); body.setDescription(description); return body; } diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java index 7e1f191a9..c6d9ca08c 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java @@ -9,8 +9,8 @@ package org.eclipse.hawkbit.mgmt.client; import org.eclipse.hawkbit.feign.core.client.FeignClientConfiguration; +import org.eclipse.hawkbit.mgmt.client.scenarios.ConfigurableScenario; import org.eclipse.hawkbit.mgmt.client.scenarios.CreateStartedRolloutExample; -import org.eclipse.hawkbit.mgmt.client.scenarios.GettingStartedDefaultScenario; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -36,7 +36,7 @@ public class Application implements CommandLineRunner { private ClientConfigurationProperties configuration; @Autowired - private GettingStartedDefaultScenario gettingStarted; + private ConfigurableScenario configurableScenario; @Autowired private CreateStartedRolloutExample gettingStartedRolloutScenario; @@ -53,7 +53,7 @@ public class Application implements CommandLineRunner { } else { // run the getting started scenario which creates a setup of // distribution set and software modules to be used - gettingStarted.run(); + configurableScenario.run(); } } @@ -63,8 +63,8 @@ public class Application implements CommandLineRunner { } @Bean - public GettingStartedDefaultScenario gettingStartedDefaultScenario() { - return new GettingStartedDefaultScenario(); + public ConfigurableScenario configurableScenario() { + return new ConfigurableScenario(); } @Bean diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java index 68f35b550..255f813f9 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java @@ -8,6 +8,9 @@ */ package org.eclipse.hawkbit.mgmt.client; +import java.util.ArrayList; +import java.util.List; + import org.springframework.boot.context.properties.ConfigurationProperties; /** @@ -34,6 +37,79 @@ public class ClientConfigurationProperties { private String password = "admin"; // NOSONAR this password is only used for // examples + private final List scenarios = new ArrayList<>(); + + public static class Scenario { + private int targets = 100; + private int distributionSets = 10; + private int appModulesPerDistributionSet = 2; + private String dsName = "Package"; + private String smSwName = "Application"; + private String smFwName = "Firmware"; + private String targetName = "Device"; + + public String getTargetName() { + return targetName; + } + + public void setTargetName(final String targetName) { + this.targetName = targetName; + } + + public String getDsName() { + return dsName; + } + + public void setDsName(final String dsName) { + this.dsName = dsName; + } + + public String getSmSwName() { + return smSwName; + } + + public void setSmSwName(final String smSwName) { + this.smSwName = smSwName; + } + + public String getSmFwName() { + return smFwName; + } + + public void setSmFwName(final String smFwName) { + this.smFwName = smFwName; + } + + public int getTargets() { + return targets; + } + + public int getDistributionSets() { + return distributionSets; + } + + public int getAppModulesPerDistributionSet() { + return appModulesPerDistributionSet; + } + + public void setTargets(final int targets) { + this.targets = targets; + } + + public void setDistributionSets(final int distributionSets) { + this.distributionSets = distributionSets; + } + + public void setAppModulesPerDistributionSet(final int appModulesPerDistributionSet) { + this.appModulesPerDistributionSet = appModulesPerDistributionSet; + } + + } + + public List getScenarios() { + return scenarios; + } + public String getUrl() { return url; } diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java new file mode 100644 index 000000000..640c12a97 --- /dev/null +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java @@ -0,0 +1,92 @@ +/** + * 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.mgmt.client.scenarios; + +import java.util.List; + +import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties; +import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties.Scenario; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource; +import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder; +import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder; +import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder; +import org.eclipse.hawkbit.mgmt.client.resource.builder.TargetBuilder; +import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * + * Default getting started scenario. + * + */ +public class ConfigurableScenario { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurableScenario.class); + + @Autowired + private MgmtDistributionSetClientResource distributionSetResource; + + @Autowired + private MgmtSoftwareModuleClientResource softwareModuleResource; + + @Autowired + private MgmtTargetClientResource targetResource; + + @Autowired + private ClientConfigurationProperties clientConfigurationProperties; + + /** + * Run the default getting started scenario. + */ + public void run() { + + LOGGER.info("Running Configurable Scenario..."); + + clientConfigurationProperties.getScenarios().parallelStream().forEach(this::createScenario); + } + + private void createScenario(final Scenario scenario) { + createTargets(scenario); + createDistributionSets(scenario); + } + + private void createDistributionSets(final Scenario scenario) { + distributionSetResource + .createDistributionSets(new DistributionSetBuilder().name(scenario.getDsName()).type("os_app") + .version("1.0.").buildAsList(scenario.getDistributionSets())) + .getBody().parallelStream().forEach(dsSet -> { + final List modules = softwareModuleResource + .createSoftwareModules(new SoftwareModuleBuilder().name(scenario.getSmFwName()) + .version(dsSet.getVersion()).type("os").build()) + .getBody(); + modules.addAll( + softwareModuleResource + .createSoftwareModules(new SoftwareModuleBuilder().name(scenario.getSmSwName()) + .version(dsSet.getVersion() + ".").type("application") + .buildAsList(scenario.getAppModulesPerDistributionSet())) + .getBody()); + + final SoftwareModuleAssigmentBuilder assign = new SoftwareModuleAssigmentBuilder(); + modules.forEach(module -> assign.id(module.getModuleId())); + + distributionSetResource.assignSoftwareModules(dsSet.getDsId(), assign.build()); + }); + } + + private void createTargets(final Scenario scenario) { + for (int i = 0; i < scenario.getTargets() / 100; i++) { + targetResource.createTargets(new TargetBuilder().controllerId(scenario.getTargetName()).buildAsList(i * 100, + (i + 1) * 100 > scenario.getTargets() ? scenario.getTargets() : (i + 1) * 100)); + } + } +} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java index 90d61471e..913d2eaa4 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java @@ -36,7 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired; public class CreateStartedRolloutExample { /* known software module type name and key */ - private static final String SM_MODULE_TYPE = "firmware"; + private static final String SM_MODULE_TYPE = "gettingstarted-rollout-example"; /* known distribution set type name and key */ private static final String DS_MODULE_TYPE = SM_MODULE_TYPE; diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/GettingStartedDefaultScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/GettingStartedDefaultScenario.java deleted file mode 100644 index fdb824e8e..000000000 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/GettingStartedDefaultScenario.java +++ /dev/null @@ -1,135 +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.mgmt.client.scenarios; - -import java.util.List; - -import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetTypeClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleTypeClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetTypeBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder; -import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleTypeBuilder; -import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; -import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; -import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; - -/** - * - * Default getting started scenario. - * - */ -public class GettingStartedDefaultScenario { - - private static final Logger LOGGER = LoggerFactory.getLogger(GettingStartedDefaultScenario.class); - - /* known software module type name and key */ - private static final String SM_MODULE_TYPE = "gettingstarted"; - - /* known distribution set type name and key */ - private static final String DS_MODULE_TYPE = SM_MODULE_TYPE; - - /* known distribution name of this getting started example */ - private static final String SM_EXAMPLE_NAME = "gettingstarted-example"; - - /* known distribution name of this getting started example */ - private static final String DS_EXAMPLE_NAME = SM_EXAMPLE_NAME; - - @Autowired - private MgmtDistributionSetClientResource distributionSetResource; - - @Autowired - private MgmtDistributionSetTypeClientResource distributionSetTypeResource; - - @Autowired - private MgmtSoftwareModuleClientResource softwareModuleResource; - - @Autowired - private MgmtSoftwareModuleTypeClientResource softwareModuleTypeResource; - - /** - * Run the default getting started scenario. - */ - public void run() { - - LOGGER.info("Running Getting-Started-Scenario..."); - - // create one SoftwareModuleTypes - LOGGER.info("Creating software module type {}", SM_MODULE_TYPE); - final List createdSoftwareModuleTypes = softwareModuleTypeResource - .createSoftwareModuleTypes(new SoftwareModuleTypeBuilder().key(SM_MODULE_TYPE).name(SM_MODULE_TYPE) - .maxAssignments(1).build()) - .getBody(); - - // create one DistributionSetType - LOGGER.info("Creating distribution set type {}", DS_MODULE_TYPE); - distributionSetTypeResource.createDistributionSetTypes(new DistributionSetTypeBuilder().key(DS_MODULE_TYPE) - .name(DS_MODULE_TYPE).mandatorymodules(createdSoftwareModuleTypes.get(0).getModuleId()).build()); - - // create three DistributionSet - final String dsVersion1 = "1.0.0"; - final String dsVersion2 = "2.0.0"; - final String dsVersion3 = "2.1.0"; - - LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion1); - final List distributionSetsRest1 = distributionSetResource.createDistributionSets( - new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion1).type(DS_MODULE_TYPE).build()) - .getBody(); - - LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion2); - final List distributionSetsRest2 = distributionSetResource.createDistributionSets( - new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion2).type(DS_MODULE_TYPE).build()) - .getBody(); - - LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion3); - final List distributionSetsRest3 = distributionSetResource.createDistributionSets( - new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion3).type(DS_MODULE_TYPE).build()) - .getBody(); - - // create three SoftwareModules - final String swVersion1 = "1"; - final String swVersion2 = "2"; - final String swVersion3 = "3"; - - LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion1); - final List softwareModulesRest1 = softwareModuleResource.createSoftwareModules( - new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion1).type(SM_MODULE_TYPE).build()) - .getBody(); - LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion2); - final List softwareModulesRest2 = softwareModuleResource.createSoftwareModules( - new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion2).type(SM_MODULE_TYPE).build()) - .getBody(); - LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion3); - final List softwareModulesRest3 = softwareModuleResource.createSoftwareModules( - new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion3).type(SM_MODULE_TYPE).build()) - .getBody(); - - // Assign SoftwareModules to DistributionSet - LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion1, - DS_EXAMPLE_NAME, dsVersion1); - distributionSetResource.assignSoftwareModules(distributionSetsRest1.get(0).getDsId(), - new SoftwareModuleAssigmentBuilder().id(softwareModulesRest1.get(0).getModuleId()).build()); - - LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion2, - DS_EXAMPLE_NAME, dsVersion2); - distributionSetResource.assignSoftwareModules(distributionSetsRest2.get(0).getDsId(), - new SoftwareModuleAssigmentBuilder().id(softwareModulesRest2.get(0).getModuleId()).build()); - - LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion3, - DS_EXAMPLE_NAME, dsVersion3); - distributionSetResource.assignSoftwareModules(distributionSetsRest3.get(0).getDsId(), - new SoftwareModuleAssigmentBuilder().id(softwareModulesRest3.get(0).getModuleId()).build()); - } -} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties index d3a3eb969..d989dcf3d 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties +++ b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties @@ -11,4 +11,13 @@ hawkbit.url=localhost:8080 hawkbit.username=admin hawkbit.password=admin -spring.main.show-banner=false \ No newline at end of file +spring.main.show-banner=false + +#hawkbit.scenarios.[0].targets=0 +#hawkbit.scenarios.[0].ds-name=gettingstarted-example +#hawkbit.scenarios.[0].distribution-sets=3 +#hawkbit.scenarios.[0].sm-fw-name=gettingstarted-example +#hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example + +hawkbit.scenarios.[0].targets=10000 +hawkbit.scenarios.[0].distribution-sets=100 \ No newline at end of file From 3e5f1f75a07e2b7d148cff211a3990be3e896601 Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Fri, 10 Jun 2016 15:47:40 +0200 Subject: [PATCH 05/46] Improve code select all table entries Signed-off-by: Melanie Retter --- .../artifacts/event/SoftwareModuleEvent.java | 6 +- .../event/SoftwareModuleTypeEvent.java | 8 +-- .../smtable/SoftwareModuleTableLayout.java | 3 +- .../filterlayout/AbstractFilterButtons.java | 24 ++++---- .../table/AbstractNamedVersionTable.java | 7 --- .../dstable/DistributionSetTableLayout.java | 7 +-- .../event/DistributionSetTableEvent.java | 60 ------------------- .../event/DistributionSetTypeEvent.java | 8 +-- 8 files changed, 19 insertions(+), 104 deletions(-) delete mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java index 1764f8998..c01257154 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java @@ -23,15 +23,11 @@ public class SoftwareModuleEvent extends BaseEntityEvent { * */ public enum SoftwareModuleEventType { - ARTIFACTS_CHANGED, ASSIGN_SOFTWARE_MODULE + ARTIFACTS_CHANGED, ASSIGN_SOFTWARE_MODULE, SELECT_ALL } private SoftwareModuleEventType softwareModuleEventType; - public SoftwareModuleEvent() { - super(null, null); - } - /** * Creates software module event. * diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java index f1b8deb72..7262aee72 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleTypeEvent.java @@ -12,20 +12,14 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType; /** * Event to represent software module type add, update or delete. - * - * - * */ public class SoftwareModuleTypeEvent { /** * Software module type events in the Upload UI. - * - * - * */ public enum SoftwareModuleTypeEnum { - ADD_SOFTWARE_MODULE_TYPE, DELETE_SOFTWARE_MODULE_TYPE, UPDATE_SOFTWARE_MODULE_TYPE, SELECT_ALL + ADD_SOFTWARE_MODULE_TYPE, DELETE_SOFTWARE_MODULE_TYPE, UPDATE_SOFTWARE_MODULE_TYPE } private SoftwareModuleType softwareModuleType; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java index 096550d7c..ec6b41e23 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.ui.artifacts.smtable; import javax.annotation.PostConstruct; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; +import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; import org.springframework.beans.factory.annotation.Autowired; @@ -72,7 +73,7 @@ public class SoftwareModuleTableLayout extends AbstractTableLayout { public void handleAction(final Action action, final Object sender, final Object target) { if (ACTION_CTRL_A.equals(action)) { smTable.selectAll(); - getEventBus().publish(this, new SoftwareModuleEvent()); + getEventBus().publish(this, new SoftwareModuleEvent(SoftwareModuleEventType.SELECT_ALL, null)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java index b637c88f6..2b0eee279 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java @@ -16,7 +16,6 @@ import javax.annotation.PreDestroy; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.decorators.SPUITagButtonStyle; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; -import org.eclipse.hawkbit.ui.utils.I18N; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; @@ -49,9 +48,6 @@ public abstract class AbstractFilterButtons extends Table { private AbstractFilterButtonClickBehaviour filterButtonClickBehaviour; - @Autowired - protected I18N i18n; - /** * Initialize layout of filter buttons. * @@ -198,16 +194,16 @@ public abstract class AbstractFilterButtons extends Table { setContainerDataSource(createButtonsLazyQueryContainer()); } - /** - * Select all rows in the table. - */ - public void selectAll() { - setValue(createButtonsLazyQueryContainer().getItemIds()); - } - - public void unSelectAll() { - setValue(null); - } + // /** + // * Select all rows in the table. + // */ + // public void selectAll() { + // setValue(createButtonsLazyQueryContainer().getItemIds()); + // } + // + // public void unSelectAll() { + // setValue(null); + // } /** * Id of the buttons table to be used in test cases. diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java index f99e01fe7..3122841ae 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java @@ -62,11 +62,4 @@ public abstract class AbstractNamedVersionTable { - - /** - * DistributionSet table components events. - * - */ - public enum DistributionSetComponentEvent { - SELECT_ALL - } - - private DistributionSetComponentEvent distributionSetComponentEvent; - - /** - * Constructor. - * - * @param eventType - * the event type. - * @param entity - * the entity - */ - public DistributionSetTableEvent(final BaseEntityEventType eventType, final DistributionSet entity) { - super(eventType, entity); - } - - /** - * The component event. - * - * @param DistributionSetTableEvent - * the distributionSet component event. - */ - public DistributionSetTableEvent(final DistributionSetComponentEvent distributionSetComponentEvent) { - super(null, null); - this.distributionSetComponentEvent = distributionSetComponentEvent; - } - - public DistributionSetComponentEvent getDistributionSetComponentEvent() { - return distributionSetComponentEvent; - } - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java index 798d2a43d..3df0a7dd3 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java @@ -11,19 +11,15 @@ package org.eclipse.hawkbit.ui.distributions.event; import org.eclipse.hawkbit.repository.model.DistributionSetType; /** - * - * + * DistributionSetTypeEvent */ public class DistributionSetTypeEvent { /** * DistributionSet type events in the Distribution UI. - * - * - * */ public enum DistributionSetTypeEnum { - ADD_DIST_SET_TYPE, DELETE_DIST_SET_TYPE, UPDATE_DIST_SET_TYPE, ON_VALUE_CHANGE + ADD_DIST_SET_TYPE, DELETE_DIST_SET_TYPE, UPDATE_DIST_SET_TYPE, ON_VALUE_CHANGE, SELECT_ALL } private DistributionSetType distributionSetType; From a9c5dcef6975bcc581117cce350b34473b06b52b Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Mon, 13 Jun 2016 09:03:01 +0200 Subject: [PATCH 06/46] Added integration option with device simulator. Signed-off-by: Kai Zimmermann --- .../resource/builder/TargetBuilder.java | 12 ++ .../hawkbit/mgmt/client/Application.java | 27 +++ .../client/ClientConfigurationProperties.java | 41 +++++ .../scenarios/ConfigurableScenario.java | 78 +++++++-- .../CreateStartedRolloutExample.java | 2 + .../client/scenarios/upload/ArtifactFile.java | 103 +++++++++++ .../upload/FeignMultipartEncoder.java | 160 ++++++++++++++++++ .../src/main/resources/application.properties | 5 +- .../model/target/MgmtTargetRequestBody.java | 11 ++ .../mgmt/rest/resource/MgmtTargetMapper.java | 1 + .../rest/resource/MgmtTargetResourceTest.java | 8 +- .../hawkbit/repository/TargetManagement.java | 19 --- .../hawkbit/repository/model/TargetInfo.java | 11 +- .../repository/jpa/JpaTargetManagement.java | 19 +-- .../repository/jpa/model/JpaTargetInfo.java | 2 +- .../hawkbit/rest/util/JsonBuilder.java | 36 ++-- 16 files changed, 459 insertions(+), 76 deletions(-) create mode 100644 examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java create mode 100644 examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java index de81f5354..023557829 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/TargetBuilder.java @@ -27,6 +27,7 @@ public class TargetBuilder { private String controllerId; private String name; private String description; + private String address; /** * @param controllerId @@ -48,6 +49,16 @@ public class TargetBuilder { return this; } + /** + * @param address + * the address of the target + * @return the builder itself + */ + public TargetBuilder address(final String address) { + this.address = address; + return this; + } + /** * @param description * the description of the target @@ -121,6 +132,7 @@ public class TargetBuilder { } body.setName(name + suffix); body.setDescription(description); + body.setAddress(address); return body; } diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java index c6d9ca08c..036c19ed1 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java @@ -9,8 +9,12 @@ package org.eclipse.hawkbit.mgmt.client; import org.eclipse.hawkbit.feign.core.client.FeignClientConfiguration; +import org.eclipse.hawkbit.feign.core.client.IgnoreMultipleConsumersProducersSpringMvcContract; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; import org.eclipse.hawkbit.mgmt.client.scenarios.ConfigurableScenario; import org.eclipse.hawkbit.mgmt.client.scenarios.CreateStartedRolloutExample; +import org.eclipse.hawkbit.mgmt.client.scenarios.upload.FeignMultipartEncoder; +import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -18,11 +22,19 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.hateoas.hal.Jackson2HalModule; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +import feign.Feign; +import feign.Logger; import feign.auth.BasicAuthRequestInterceptor; +import feign.jackson.JacksonDecoder; @SpringBootApplication @EnableFeignClients @@ -72,6 +84,21 @@ public class Application implements CommandLineRunner { return new CreateStartedRolloutExample(); } + @Bean + public MgmtSoftwareModuleClientResource uploadSoftwareModule() { + final ObjectMapper mapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .registerModule(new Jackson2HalModule()); + + return Feign.builder().contract(new IgnoreMultipleConsumersProducersSpringMvcContract()) + .requestInterceptor( + new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword())) + .logger(new Logger.ErrorLogger()).encoder(new FeignMultipartEncoder()) + .decoder(new ResponseEntityDecoder(new JacksonDecoder(mapper))) + .target(MgmtSoftwareModuleClientResource.class, + configuration.getUrl() + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING); + } + private boolean containsArg(final String containsArg, final String... args) { for (final String arg : args) { if (arg.equalsIgnoreCase(containsArg)) { diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java index 255f813f9..cc5fe27e9 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java @@ -40,6 +40,7 @@ public class ClientConfigurationProperties { private final List scenarios = new ArrayList<>(); public static class Scenario { + private String tenant = "DEFAULT"; private int targets = 100; private int distributionSets = 10; private int appModulesPerDistributionSet = 2; @@ -47,6 +48,46 @@ public class ClientConfigurationProperties { private String smSwName = "Application"; private String smFwName = "Firmware"; private String targetName = "Device"; + private int artifactsPerSM = 1; + private String targetAddress = "amqp:/simulator.replyTo"; + + /** + * Artifact size. Values can use the suffixed "MB" or "KB" to indicate a + * Megabyte or Kilobyte size. + */ + private String artifactSize = "1MB"; + + public String getTargetAddress() { + return targetAddress; + } + + public void setTargetAddress(final String targetAddress) { + this.targetAddress = targetAddress; + } + + public String getTenant() { + return tenant; + } + + public void setTenant(final String tenant) { + this.tenant = tenant; + } + + public int getArtifactsPerSM() { + return artifactsPerSM; + } + + public void setArtifactsPerSM(final int artifactsPerSM) { + this.artifactsPerSM = artifactsPerSM; + } + + public String getArtifactSize() { + return artifactSize; + } + + public void setArtifactSize(final String artifactSize) { + this.artifactSize = artifactSize; + } public String getTargetName() { return targetName; diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java index 640c12a97..60144a88e 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java @@ -9,20 +9,25 @@ package org.eclipse.hawkbit.mgmt.client.scenarios; import java.util.List; +import java.util.Random; import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties; import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties.Scenario; import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource; import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtSystemManagementClientResource; import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource; import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder; import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder; import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder; import org.eclipse.hawkbit.mgmt.client.resource.builder.TargetBuilder; +import org.eclipse.hawkbit.mgmt.client.scenarios.upload.ArtifactFile; +import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; /** * @@ -37,11 +42,19 @@ public class ConfigurableScenario { private MgmtDistributionSetClientResource distributionSetResource; @Autowired + @Qualifier("mgmtSoftwareModuleClientResource") private MgmtSoftwareModuleClientResource softwareModuleResource; + @Autowired + @Qualifier("uploadSoftwareModule") + private MgmtSoftwareModuleClientResource uploadSoftwareModule; + @Autowired private MgmtTargetClientResource targetResource; + @Autowired + private MgmtSystemManagementClientResource systemManagementResource; + @Autowired private ClientConfigurationProperties clientConfigurationProperties; @@ -56,37 +69,76 @@ public class ConfigurableScenario { } private void createScenario(final Scenario scenario) { + systemManagementResource.deleteTenant(scenario.getTenant()); createTargets(scenario); createDistributionSets(scenario); } private void createDistributionSets(final Scenario scenario) { + final byte[] artifact = generateArtifact(scenario); + distributionSetResource .createDistributionSets(new DistributionSetBuilder().name(scenario.getDsName()).type("os_app") .version("1.0.").buildAsList(scenario.getDistributionSets())) .getBody().parallelStream().forEach(dsSet -> { - final List modules = softwareModuleResource - .createSoftwareModules(new SoftwareModuleBuilder().name(scenario.getSmFwName()) - .version(dsSet.getVersion()).type("os").build()) - .getBody(); - modules.addAll( - softwareModuleResource - .createSoftwareModules(new SoftwareModuleBuilder().name(scenario.getSmSwName()) - .version(dsSet.getVersion() + ".").type("application") - .buildAsList(scenario.getAppModulesPerDistributionSet())) - .getBody()); + final List modules = addModules(scenario, dsSet, artifact); final SoftwareModuleAssigmentBuilder assign = new SoftwareModuleAssigmentBuilder(); modules.forEach(module -> assign.id(module.getModuleId())); - distributionSetResource.assignSoftwareModules(dsSet.getDsId(), assign.build()); }); } + private List addModules(final Scenario scenario, final MgmtDistributionSet dsSet, + final byte[] artifact) { + final List modules = softwareModuleResource.createSoftwareModules( + new SoftwareModuleBuilder().name(scenario.getSmFwName()).version(dsSet.getVersion()).type("os").build()) + .getBody(); + modules.addAll(softwareModuleResource + .createSoftwareModules( + new SoftwareModuleBuilder().name(scenario.getSmSwName()).version(dsSet.getVersion() + ".") + .type("application").buildAsList(scenario.getAppModulesPerDistributionSet())) + .getBody()); + + for (int x = 0; x < scenario.getArtifactsPerSM(); x++) { + modules.forEach(module -> { + final ArtifactFile file = new ArtifactFile("dummyfile.dummy", null, "multipart/form-data", artifact); + uploadSoftwareModule.uploadArtifact(module.getModuleId(), file, null, null, null); + }); + } + + return modules; + } + + private byte[] generateArtifact(final Scenario scenario) { + // create random object + final Random random = new Random(); + + // create byte array + final byte[] nbyte = new byte[parseSize(scenario.getArtifactSize())]; + + // put the next byte in the array + random.nextBytes(nbyte); + + return nbyte; + } + private void createTargets(final Scenario scenario) { for (int i = 0; i < scenario.getTargets() / 100; i++) { - targetResource.createTargets(new TargetBuilder().controllerId(scenario.getTargetName()).buildAsList(i * 100, - (i + 1) * 100 > scenario.getTargets() ? scenario.getTargets() : (i + 1) * 100)); + targetResource.createTargets(new TargetBuilder().controllerId(scenario.getTargetName()) + .address(scenario.getTargetAddress()).buildAsList(i * 100, + (i + 1) * 100 > scenario.getTargets() ? scenario.getTargets() - i * 100 : 100)); } } + + private int parseSize(final String s) { + final String size = s.toUpperCase(); + if (size.endsWith("KB")) { + return Integer.valueOf(size.substring(0, size.length() - 2)) * 1024; + } + if (size.endsWith("MB")) { + return Integer.valueOf(size.substring(0, size.length() - 2)) * 1024 * 1024; + } + return Integer.valueOf(size); + } } diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java index 913d2eaa4..b450bbde2 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/CreateStartedRolloutExample.java @@ -28,6 +28,7 @@ import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleType; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; /** * Example for creating and starting a Rollout. @@ -45,6 +46,7 @@ public class CreateStartedRolloutExample { private MgmtDistributionSetClientResource distributionSetResource; @Autowired + @Qualifier("mgmtSoftwareModuleClientResource") private MgmtSoftwareModuleClientResource softwareModuleResource; @Autowired diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java new file mode 100644 index 000000000..adad1fe77 --- /dev/null +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java @@ -0,0 +1,103 @@ +/** + * 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.mgmt.client.scenarios.upload; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import org.springframework.util.Assert; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.multipart.MultipartFile; + +public class ArtifactFile implements MultipartFile { + + private final String name; + + private final String originalFilename; + + private final String contentType; + + private final byte[] content; + + /** + * Create a new ArtifactFile with the given content. + * + * @param name + * the name of the file + * @param content + * the content of the file + */ + public ArtifactFile(final String name, final byte[] content) { + this(name, "", null, content); + } + + /** + * Create a new ArtifactFile with the given content. + * + * @param name + * of the file + * @param originalFilename + * the original filename (as on the client's machine) + * @param contentType + * the content type + * @param content + * of the file + */ + public ArtifactFile(final String name, final String originalFilename, final String contentType, + final byte[] content) { + Assert.hasLength(name, "Name must not be null"); + this.name = name; + this.originalFilename = originalFilename != null ? originalFilename : ""; + this.contentType = contentType; + this.content = content != null ? content : new byte[0]; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String getOriginalFilename() { + return this.originalFilename; + } + + @Override + public String getContentType() { + return this.contentType; + } + + @Override + public boolean isEmpty() { + return this.content.length == 0; + } + + @Override + public long getSize() { + return this.content.length; + } + + @Override + public byte[] getBytes() throws IOException { + return this.content; + } + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(this.content); + } + + @Override + public void transferTo(final File dest) throws IOException { + FileCopyUtils.copy(this.content, dest); + } + +} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java new file mode 100644 index 000000000..fdf5462da --- /dev/null +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved. + */ +package org.eclipse.hawkbit.mgmt.client.scenarios.upload; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Type; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map.Entry; + +import org.springframework.core.io.InputStreamResource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.multipart.MultipartFile; + +import feign.RequestTemplate; +import feign.codec.EncodeException; +import feign.codec.Encoder; + +/** + * A feign encoder implementation which handles {@link MultipartFile} body. + */ +public class FeignMultipartEncoder implements Encoder { + + private final List> converters = new RestTemplate().getMessageConverters(); + private final HttpHeaders multipartHeaders = new HttpHeaders(); + private final HttpHeaders jsonHeaders = new HttpHeaders(); + + public static final Charset UTF_8 = Charset.forName("UTF-8"); + + public FeignMultipartEncoder() { + multipartHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); + jsonHeaders.setContentType(MediaType.APPLICATION_JSON); + } + + @Override + public void encode(final Object object, final Type bodyType, final RequestTemplate template) + throws EncodeException { + + encodeMultipartFormRequest(object, template); + + } + + private void encodeMultipartFormRequest(final Object value, final RequestTemplate template) { + if (value == null) { + throw new EncodeException("Cannot encode request with null value."); + } + if (!isMultipartFile(value)) { + throw new EncodeException("Only multipart can be handled by this encoder"); + } + encodeRequest(encodeMultipartFile((MultipartFile) value), multipartHeaders, template); + } + + @SuppressWarnings("unchecked") + private void encodeRequest(final Object value, final HttpHeaders requestHeaders, final RequestTemplate template) + throws EncodeException { + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + final HttpOutputMessage dummyRequest = new HttpOutputMessageImpl(outputStream, requestHeaders); + try { + final Class requestType = value.getClass(); + final MediaType requestContentType = requestHeaders.getContentType(); + for (final HttpMessageConverter messageConverter : converters) { + if (messageConverter.canWrite(requestType, requestContentType)) { + ((HttpMessageConverter) messageConverter).write(value, requestContentType, dummyRequest); + break; + } + } + } catch (final IOException ex) { + throw new EncodeException("Cannot encode request.", ex); + } + final HttpHeaders headers = dummyRequest.getHeaders(); + if (headers != null) { + for (final Entry> entry : headers.entrySet()) { + template.header(entry.getKey(), entry.getValue()); + } + } + /* + * we should use a template output stream... this will cause issues if + * files are too big, since the whole request will be in memory. + */ + template.body(outputStream.toByteArray(), UTF_8); + } + + private MultiValueMap encodeMultipartFile(final MultipartFile file) { + try { + final MultiValueMap multiValueMap = new LinkedMultiValueMap<>(); + multiValueMap.add("file", new MultipartFileResource(file.getName(), file.getSize(), file.getInputStream())); + return multiValueMap; + } catch (final IOException ex) { + throw new EncodeException("Cannot encode request.", ex); + } + } + + private boolean isMultipartFile(final Object object) { + return object instanceof MultipartFile; + } + + private class HttpOutputMessageImpl implements HttpOutputMessage { + + private final OutputStream body; + private final HttpHeaders headers; + + public HttpOutputMessageImpl(final OutputStream body, final HttpHeaders headers) { + this.body = body; + this.headers = headers; + } + + @Override + public OutputStream getBody() throws IOException { + return body; + } + + @Override + public HttpHeaders getHeaders() { + return headers; + } + + } + + /** + * Dummy resource class. Wraps file content and its original name. + */ + static class MultipartFileResource extends InputStreamResource { + + private final String filename; + private final long size; + + public MultipartFileResource(final String filename, final long size, final InputStream inputStream) { + super(inputStream); + this.size = size; + this.filename = filename; + } + + @Override + public String getFilename() { + return this.filename; + } + + @Override + public InputStream getInputStream() throws IOException, IllegalStateException { + return super.getInputStream(); // To change body of generated + // methods, choose Tools | Templates. + } + + @Override + public long contentLength() throws IOException { + return size; + } + + } +} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties index d989dcf3d..f538bb1cb 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties +++ b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties @@ -7,7 +7,7 @@ # http://www.eclipse.org/legal/epl-v10.html # -hawkbit.url=localhost:8080 +hawkbit.url=http://localhost:8080 hawkbit.username=admin hawkbit.password=admin @@ -20,4 +20,5 @@ spring.main.show-banner=false #hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example hawkbit.scenarios.[0].targets=10000 -hawkbit.scenarios.[0].distribution-sets=100 \ No newline at end of file +hawkbit.scenarios.[0].distribution-sets=100 +hawkbit.scenarios.[0].artifactsPerSM=0 \ No newline at end of file diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java index bc40326e4..b9c0b001a 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/target/MgmtTargetRequestBody.java @@ -18,6 +18,9 @@ public class MgmtTargetRequestBody { @JsonProperty(required = true) private String controllerId; + @JsonProperty + private String address; + /** * @return the name */ @@ -66,4 +69,12 @@ public class MgmtTargetRequestBody { return this; } + public String getAddress() { + return address; + } + + public void setAddress(final String address) { + this.address = address; + } + } diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java index f00998d29..d77cbaa53 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java @@ -182,6 +182,7 @@ public final class MgmtTargetMapper { final Target target = entityFactory.generateTarget(targetRest.getControllerId()); target.setDescription(targetRest.getDescription()); target.setName(targetRest.getName()); + target.getTargetInfo().setAddress(targetRest.getAddress()); return target; } diff --git a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java index 1375307d4..ed6ee4a93 100644 --- a/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java +++ b/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResourceTest.java @@ -40,11 +40,11 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetInfo; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.Status; -import org.eclipse.hawkbit.repository.test.util.WithUser; import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.repository.test.util.WithUser; import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest; import org.eclipse.hawkbit.rest.exception.MessageNotReadableException; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; @@ -109,8 +109,8 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest { final String knownTargetId = "targetId"; final List actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId); actions.get(0).setStatus(Status.FINISHED); - controllerManagament.addUpdateActionStatus(entityFactory.generateActionStatus(actions.get(0), - Status.FINISHED, System.currentTimeMillis(), "testmessage")); + controllerManagament.addUpdateActionStatus(entityFactory.generateActionStatus(actions.get(0), Status.FINISHED, + System.currentTimeMillis(), "testmessage")); final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionFields.ID.getFieldName()); final ActionStatus status = deploymentManagement @@ -682,6 +682,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest { final Target test1 = entityFactory.generateTarget("id1"); test1.setDescription("testid1"); test1.setName("testname1"); + test1.getTargetInfo().setAddress("amqp://test123/foobar"); final Target test2 = entityFactory.generateTarget("id2"); test2.setDescription("testid2"); test2.setName("testname2"); @@ -704,6 +705,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest { .andExpect(jsonPath("[0].description", equalTo("testid1"))) .andExpect(jsonPath("[0].createdAt", not(equalTo(0)))) .andExpect(jsonPath("[0].createdBy", equalTo("bumlux"))) + .andExpect(jsonPath("[0].address", equalTo("amqp://test123/foobar"))) .andExpect(jsonPath("[1].name", equalTo("testname2"))) .andExpect(jsonPath("[1].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("[1].controllerId", equalTo("id2"))) diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java index 9054127ef..5fdfb318e 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java @@ -179,25 +179,6 @@ public interface TargetManagement { @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) List createTargets(@NotNull Collection targets); - /** - * creating a new {@link Target} including poll status data. useful - * especially in plug and play scenarios. - * - * @param targets - * to be created * - * @param status - * of the target - * @param lastTargetQuery - * if a plug and play case - * @param address - * if a plug and play case - * - * @return newly created target - */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET) - List createTargets(@NotNull Collection targets, @NotNull TargetUpdateStatus status, - Long lastTargetQuery, URI address); - /** * Deletes all targets with the given IDs. * diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetInfo.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetInfo.java index 6317f9783..2eb2f05c7 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetInfo.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/TargetInfo.java @@ -16,10 +16,19 @@ import java.util.concurrent.TimeUnit; public interface TargetInfo extends Serializable { /** - * @return the address under whioch the target can be reached + * @return the address under which the target can be reached */ URI getAddress(); + /** + * @param address + * the target address to set + * + * @throws IllegalArgumentException + * If the given string violates RFC 2396 + */ + void setAddress(String address); + /** * @return {@link Target} this info element belongs to. */ 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 892ddc771..f318962bf 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 @@ -608,24 +608,7 @@ public class JpaTargetManagement implements TargetManagement { } final List savedTargets = new ArrayList<>(); for (final Target t : targets) { - final Target myTarget = createTarget(t); - savedTargets.add(myTarget); - } - return savedTargets; - } - - @Override - @Modifying - @Transactional(isolation = Isolation.READ_UNCOMMITTED) - public List createTargets(final Collection targets, final TargetUpdateStatus status, - final Long lastTargetQuery, final URI address) { - if (targetRepository.countByControllerIdIn( - targets.stream().map(target -> target.getControllerId()).collect(Collectors.toList())) > 0) { - throw new EntityAlreadyExistsException(); - } - final List savedTargets = new ArrayList<>(); - for (final Target t : targets) { - final Target myTarget = createTarget(t, status, lastTargetQuery, address); + final Target myTarget = createTarget(t, TargetUpdateStatus.UNKNOWN, null, t.getTargetInfo().getAddress()); savedTargets.add(myTarget); } return savedTargets; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java index 6b5a3d1af..15abc2d61 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java @@ -168,7 +168,7 @@ public class JpaTargetInfo implements Persistable, TargetInfo { /** * @param address - * the ipAddress to set + * the target address to set * * @throws IllegalArgumentException * If the given string violates RFC 2396 diff --git a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java index f67f15815..51cbd7a99 100644 --- a/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java +++ b/hawkbit-rest-core/src/test/java/org/eclipse/hawkbit/rest/util/JsonBuilder.java @@ -41,9 +41,9 @@ public abstract class JsonBuilder { try { builder.append(new JSONObject().put("name", module.getName()) .put("description", module.getDescription()).put("type", module.getType().getKey()) - .put("id", Long.MAX_VALUE).put("vendor", module.getVendor()) - .put("version", module.getVersion()).put("createdAt", "0").put("updatedAt", "0") - .put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh").toString()); + .put("id", Long.MAX_VALUE).put("vendor", module.getVendor()).put("version", module.getVersion()) + .put("createdAt", "0").put("updatedAt", "0").put("createdBy", "fghdfkjghdfkjh") + .put("updatedBy", "fghdfkjghdfkjh").toString()); } catch (final Exception e) { e.printStackTrace(); } @@ -185,15 +185,13 @@ public abstract class JsonBuilder { final List messages = new ArrayList(); messages.add(message); - return new JSONObject() - .put("id", id) - .put("time", "20140511T121314") + return new JSONObject().put("id", id).put("time", "20140511T121314") .put("status", - new JSONObject() - .put("execution", execution) + new JSONObject().put("execution", execution) .put("result", new JSONObject().put("finished", finished).put("progress", - new JSONObject().put("cnt", 2).put("of", 5))).put("details", messages)) + new JSONObject().put("cnt", 2).put("of", 5))) + .put("details", messages)) .toString(); } @@ -380,10 +378,13 @@ public abstract class JsonBuilder { int i = 0; for (final Target target : targets) { try { + final String address = target.getTargetInfo().getAddress() != null + ? target.getTargetInfo().getAddress().toString() : null; + builder.append(new JSONObject().put("controllerId", target.getControllerId()) - .put("description", target.getDescription()).put("name", target.getName()) - .put("createdAt", "0").put("updatedAt", "0").put("createdBy", "fghdfkjghdfkjh") - .put("updatedBy", "fghdfkjghdfkjh").toString()); + .put("description", target.getDescription()).put("name", target.getName()).put("createdAt", "0") + .put("updatedAt", "0").put("createdBy", "fghdfkjghdfkjh").put("updatedBy", "fghdfkjghdfkjh") + .put("address", address).toString()); } catch (final Exception e) { e.printStackTrace(); } @@ -441,9 +442,7 @@ public abstract class JsonBuilder { throws JSONException { final List messages = new ArrayList(); messages.add(message); - return new JSONObject() - .put("id", id) - .put("time", "20140511T121314") + return new JSONObject().put("id", id).put("time", "20140511T121314") .put("status", new JSONObject().put("execution", execution) .put("result", new JSONObject().put("finished", "success")).put("details", messages)) @@ -453,13 +452,12 @@ public abstract class JsonBuilder { public static String configData(final String id, final Map attributes, final String execution) throws JSONException { - return new JSONObject() - .put("id", id) - .put("time", "20140511T121314") + return new JSONObject().put("id", id).put("time", "20140511T121314") .put("status", new JSONObject().put("execution", execution) .put("result", new JSONObject().put("finished", "success")) - .put("details", new ArrayList())).put("data", attributes).toString(); + .put("details", new ArrayList())) + .put("data", attributes).toString(); } From 1b5975523947795ecd5e38e2d20992e90448b23e Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Mon, 13 Jun 2016 17:49:09 +0200 Subject: [PATCH 07/46] Optimize multiselect Signed-off-by: Melanie Retter --- .../filterlayout/AbstractFilterButtons.java | 12 --------- .../dstable/DistributionSetTableLayout.java | 7 +++--- .../event/DistributionSetTableEvent.java | 25 +++++++++++++++++++ .../event/DistributionSetTypeEvent.java | 2 +- .../event/SoftwareModuleTableEvent.java | 25 +++---------------- .../dstable/DistributionTableLayout.java | 7 +++--- .../event/DistributionTableEvent.java | 23 ++--------------- .../ui/management/event/TargetTableEvent.java | 4 +-- 8 files changed, 41 insertions(+), 64 deletions(-) create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java index 2b0eee279..aec0029d0 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/filterlayout/AbstractFilterButtons.java @@ -77,7 +77,6 @@ public abstract class AbstractFilterButtons extends Table { setDragMode(TableDragMode.NONE); setSelectable(false); setSizeFull(); - setMultiSelect(true); } private void setStyle() { @@ -194,17 +193,6 @@ public abstract class AbstractFilterButtons extends Table { setContainerDataSource(createButtonsLazyQueryContainer()); } - // /** - // * Select all rows in the table. - // */ - // public void selectAll() { - // setValue(createButtonsLazyQueryContainer().getItemIds()); - // } - // - // public void unSelectAll() { - // setValue(null); - // } - /** * Id of the buttons table to be used in test cases. * diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java index ef6d3ae4a..cf365b081 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java @@ -11,8 +11,8 @@ package org.eclipse.hawkbit.ui.distributions.dstable; import javax.annotation.PostConstruct; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTypeEvent.DistributionSetTypeEnum; +import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent; +import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent.DistributionTableComponentEvent; import org.springframework.beans.factory.annotation.Autowired; import com.vaadin.event.Action; @@ -77,7 +77,8 @@ public class DistributionSetTableLayout extends AbstractTableLayout { public void handleAction(final Action action, final Object sender, final Object target) { if (ACTION_CTRL_A.equals(action)) { dsTable.selectAll(); - getEventBus().publish(this, new DistributionSetTypeEvent(DistributionSetTypeEnum.SELECT_ALL)); + getEventBus().publish(this, + new DistributionSetTableEvent(DistributionTableComponentEvent.SELECT_ALL)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java new file mode 100644 index 000000000..d1a5643a1 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java @@ -0,0 +1,25 @@ +package org.eclipse.hawkbit.ui.distributions.event; + +public class DistributionSetTableEvent { + + private final DistributionTableComponentEvent distributionSetTableEvent; + + /** + * The component event. + * + * @param distributionSetTableEvent + * the distributionSet component event. + */ + public DistributionSetTableEvent(final DistributionTableComponentEvent distributionSetTableEvent) { + this.distributionSetTableEvent = distributionSetTableEvent; + } + + /** + * DistributionSet table components events. + * + */ + public enum DistributionTableComponentEvent { + SELECT_ALL + } + +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java index 3df0a7dd3..c6a625b10 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTypeEvent.java @@ -19,7 +19,7 @@ public class DistributionSetTypeEvent { * DistributionSet type events in the Distribution UI. */ public enum DistributionSetTypeEnum { - ADD_DIST_SET_TYPE, DELETE_DIST_SET_TYPE, UPDATE_DIST_SET_TYPE, ON_VALUE_CHANGE, SELECT_ALL + ADD_DIST_SET_TYPE, DELETE_DIST_SET_TYPE, UPDATE_DIST_SET_TYPE, ON_VALUE_CHANGE } private DistributionSetType distributionSetType; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java index f722c3a23..772afd927 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java @@ -8,36 +8,20 @@ */ package org.eclipse.hawkbit.ui.distributions.event; -import org.eclipse.hawkbit.repository.model.SoftwareModule; -import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent; -import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; - /** - * Class which contains the Event when selecting all entries of a table + * Class which contains the Event when selecting all entries of the + * softwareModule table */ -public class SoftwareModuleTableEvent extends BaseEntityEvent { +public class SoftwareModuleTableEvent { /** * SoftwareModule table components events. - * */ public enum SoftwareModuleComponentEvent { SELECT_ALL } - private SoftwareModuleComponentEvent softwareModuleComponentEvent; - - /** - * Constructor. - * - * @param eventType - * the event type. - * @param entity - * the entity - */ - public SoftwareModuleTableEvent(final BaseEntityEventType eventType, final SoftwareModule entity) { - super(eventType, entity); - } + private final SoftwareModuleComponentEvent softwareModuleComponentEvent; /** * The component event. @@ -46,7 +30,6 @@ public class SoftwareModuleTableEvent extends BaseEntityEvent { * the softwareModule component event. */ public SoftwareModuleTableEvent(final SoftwareModuleComponentEvent softwareModuleComponentEvent) { - super(null, null); this.softwareModuleComponentEvent = softwareModuleComponentEvent; } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java index 213dda654..2cd34d3fa 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java @@ -11,8 +11,8 @@ package org.eclipse.hawkbit.ui.management.dstable; import javax.annotation.PostConstruct; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; -import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent; -import org.eclipse.hawkbit.ui.management.event.DistributionTableEvent.DistributionTableComponentEvent; +import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent; +import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent.DistributionTableComponentEvent; import org.springframework.beans.factory.annotation.Autowired; import com.vaadin.event.Action; @@ -73,7 +73,8 @@ public class DistributionTableLayout extends AbstractTableLayout { public void handleAction(final Action action, final Object sender, final Object target) { if (ACTION_CTRL_A.equals(action)) { dsTable.selectAll(); - getEventBus().publish(this, new DistributionTableEvent(DistributionTableComponentEvent.SELECT_ALL)); + getEventBus().publish(this, + new DistributionSetTableEvent(DistributionTableComponentEvent.SELECT_ALL)); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTableEvent.java index e60f432e7..c35942682 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTableEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/DistributionTableEvent.java @@ -13,20 +13,11 @@ import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; /** - * - * - * + * Class which contains the Event when selecting all entries of the + * distributions table */ public class DistributionTableEvent extends BaseEntityEvent { - /** - * DistributionSet table components events. - * - */ - public enum DistributionTableComponentEvent { - SELECT_ALL - } - /** * Constructor. * @@ -39,14 +30,4 @@ public class DistributionTableEvent extends BaseEntityEvent { super(eventType, entity); } - /** - * The component event. - * - * @param DistributionSetTableEvent - * the distributionSet component event. - */ - public DistributionTableEvent(final DistributionTableComponentEvent distributionComponentEvent) { - super(null, null); - } - } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java index 04dd917a9..4cfbeecf5 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java @@ -13,9 +13,7 @@ import org.eclipse.hawkbit.ui.common.table.BaseEntityEvent; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; /** - * - * - * + * Class which contains the Event when selecting all entries of the target table */ public class TargetTableEvent extends BaseEntityEvent { From 23b00999e66a72b7619e22df131a5a4aadcf1dc7 Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Tue, 14 Jun 2016 11:02:16 +0200 Subject: [PATCH 08/46] fix softwaremodule Event Signed-off-by: Melanie Retter --- .../hawkbit/ui/artifacts/event/SoftwareModuleEvent.java | 2 +- .../ui/artifacts/smtable/SoftwareModuleTableLayout.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java index c01257154..95770cb8f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/event/SoftwareModuleEvent.java @@ -23,7 +23,7 @@ public class SoftwareModuleEvent extends BaseEntityEvent { * */ public enum SoftwareModuleEventType { - ARTIFACTS_CHANGED, ASSIGN_SOFTWARE_MODULE, SELECT_ALL + ARTIFACTS_CHANGED, ASSIGN_SOFTWARE_MODULE } private SoftwareModuleEventType softwareModuleEventType; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java index ec6b41e23..a0ed1b4ec 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java @@ -10,9 +10,9 @@ package org.eclipse.hawkbit.ui.artifacts.smtable; import javax.annotation.PostConstruct; -import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; -import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent.SoftwareModuleEventType; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; +import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent; +import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent.SoftwareModuleComponentEvent; import org.springframework.beans.factory.annotation.Autowired; import com.vaadin.event.Action; @@ -73,7 +73,7 @@ public class SoftwareModuleTableLayout extends AbstractTableLayout { public void handleAction(final Action action, final Object sender, final Object target) { if (ACTION_CTRL_A.equals(action)) { smTable.selectAll(); - getEventBus().publish(this, new SoftwareModuleEvent(SoftwareModuleEventType.SELECT_ALL, null)); + getEventBus().publish(this, new SoftwareModuleTableEvent(SoftwareModuleComponentEvent.SELECT_ALL)); } } From c3f2c4fc70bb582ae61fe5a73eaffe8474c8d086 Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Tue, 14 Jun 2016 13:24:58 +0200 Subject: [PATCH 09/46] Refactor multiselect code Signed-off-by: Melanie Retter --- .../smtable/SoftwareModuleTableLayout.java | 40 +---------------- .../table/AbstractNamedVersionTable.java | 8 ---- .../ui/common/table/AbstractTable.java | 8 ++++ .../ui/common/table/AbstractTableLayout.java | 27 ++++++++++-- .../dstable/DistributionSetTableLayout.java | 43 ++----------------- .../event/DistributionSetTableEvent.java | 25 ----------- .../event/SoftwareModuleTableEvent.java | 40 ----------------- .../smtable/SwModuleTableLayout.java | 42 ++---------------- .../dstable/DistributionTableLayout.java | 41 +----------------- .../ui/management/event/TargetTableEvent.java | 2 +- .../management/footer/CountMessageLabel.java | 2 +- .../targettable/TargetTableLayout.java | 39 ++--------------- 12 files changed, 47 insertions(+), 270 deletions(-) delete mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java delete mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java index a0ed1b4ec..2672c4546 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java @@ -11,12 +11,8 @@ package org.eclipse.hawkbit.ui.artifacts.smtable; import javax.annotation.PostConstruct; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; -import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent; -import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent.SoftwareModuleComponentEvent; import org.springframework.beans.factory.annotation.Autowired; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; @@ -46,41 +42,9 @@ public class SoftwareModuleTableLayout extends AbstractTableLayout { super.init(smTableHeader, smTable, softwareModuleDetails); } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * isShortCutKeysRequired() - */ @Override - protected boolean isShortCutKeysRequired() { - return true; + protected void publishEvent() { + // nothing to publish } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * getShortCutKeysHandler() - */ - @Override - protected Handler getShortCutKeysHandler() { - return new Handler() { - - private static final long serialVersionUID = 1L; - - @Override - public void handleAction(final Action action, final Object sender, final Object target) { - if (ACTION_CTRL_A.equals(action)) { - smTable.selectAll(); - getEventBus().publish(this, new SoftwareModuleTableEvent(SoftwareModuleComponentEvent.SELECT_ALL)); - } - } - - @Override - public Action[] getActions(final Object target, final Object sender) { - return new Action[] { ACTION_CTRL_A }; - } - }; - } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java index 3122841ae..ae185a70f 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractNamedVersionTable.java @@ -54,12 +54,4 @@ public abstract class AbstractNamedVersionTable extends Table { } } + /** + * Select all rows in the table. + */ + protected void selectAll() { + // only contains the ItemIds of the visible items in the table + setValue(getItemIds()); + } + private void setColumnProperties() { final List columnList = getTableVisibleColumns(); final List swColumnIds = new ArrayList<>(); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java index 9406dcb93..b85006468 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java @@ -12,6 +12,7 @@ import org.eclipse.hawkbit.ui.common.detailslayout.AbstractTableDetailsLayout; import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.spring.events.EventBus; +import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.ShortcutAction; import com.vaadin.ui.Alignment; @@ -89,10 +90,10 @@ public abstract class AbstractTableLayout extends VerticalLayout { /** * If any short cut keys required on the table. * - * @return true if required else false. Default is 'false'. + * @return true if required else false. Default is 'true'. */ protected boolean isShortCutKeysRequired() { - return false; + return true; } /** @@ -101,7 +102,27 @@ public abstract class AbstractTableLayout extends VerticalLayout { * @return reference of {@link Handler} to handler the short cut keys. * Default is null. */ - protected abstract Handler getShortCutKeysHandler(); + protected Handler getShortCutKeysHandler() { + return new Handler() { + + private static final long serialVersionUID = 1L; + + @Override + public void handleAction(final Action action, final Object sender, final Object target) { + if (ACTION_CTRL_A.equals(action)) { + table.selectAll(); + publishEvent(); + } + } + + @Override + public Action[] getActions(final Object target, final Object sender) { + return new Action[] { ACTION_CTRL_A }; + } + }; + } + + protected abstract void publishEvent(); public void setShowFilterButtonVisible(final boolean visible) { tableHeader.setFilterButtonsIconVisible(visible); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java index cf365b081..66c8aff0e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java @@ -11,17 +11,13 @@ package org.eclipse.hawkbit.ui.distributions.dstable; import javax.annotation.PostConstruct; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent.DistributionTableComponentEvent; import org.springframework.beans.factory.annotation.Autowired; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; /** - * DistributionSet table layout. + * DistributionSet table layout */ @SpringComponent @ViewScope @@ -50,42 +46,9 @@ public class DistributionSetTableLayout extends AbstractTableLayout { super.init(dsTableHeader, dsTable, distributionDetails); } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * isShortCutKeysRequired() - */ @Override - protected boolean isShortCutKeysRequired() { - return true; + protected void publishEvent() { + // nothing to publish } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * getShortCutKeysHandler() - */ - @Override - protected Handler getShortCutKeysHandler() { - return new Handler() { - - private static final long serialVersionUID = 1L; - - @Override - public void handleAction(final Action action, final Object sender, final Object target) { - if (ACTION_CTRL_A.equals(action)) { - dsTable.selectAll(); - getEventBus().publish(this, - new DistributionSetTableEvent(DistributionTableComponentEvent.SELECT_ALL)); - } - } - - @Override - public Action[] getActions(final Object target, final Object sender) { - return new Action[] { ACTION_CTRL_A }; - } - }; - } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java deleted file mode 100644 index d1a5643a1..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/DistributionSetTableEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.eclipse.hawkbit.ui.distributions.event; - -public class DistributionSetTableEvent { - - private final DistributionTableComponentEvent distributionSetTableEvent; - - /** - * The component event. - * - * @param distributionSetTableEvent - * the distributionSet component event. - */ - public DistributionSetTableEvent(final DistributionTableComponentEvent distributionSetTableEvent) { - this.distributionSetTableEvent = distributionSetTableEvent; - } - - /** - * DistributionSet table components events. - * - */ - public enum DistributionTableComponentEvent { - SELECT_ALL - } - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java deleted file mode 100644 index 772afd927..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/event/SoftwareModuleTableEvent.java +++ /dev/null @@ -1,40 +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.distributions.event; - -/** - * Class which contains the Event when selecting all entries of the - * softwareModule table - */ -public class SoftwareModuleTableEvent { - - /** - * SoftwareModule table components events. - */ - public enum SoftwareModuleComponentEvent { - SELECT_ALL - } - - private final SoftwareModuleComponentEvent softwareModuleComponentEvent; - - /** - * The component event. - * - * @param softwareModuleComponentEvent - * the softwareModule component event. - */ - public SoftwareModuleTableEvent(final SoftwareModuleComponentEvent softwareModuleComponentEvent) { - this.softwareModuleComponentEvent = softwareModuleComponentEvent; - } - - public SoftwareModuleComponentEvent getSoftwareModuleComponentEvent() { - return softwareModuleComponentEvent; - } - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java index b2fab5cc9..e0d4b8ac6 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java @@ -11,17 +11,13 @@ package org.eclipse.hawkbit.ui.distributions.smtable; import javax.annotation.PostConstruct; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; -import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent; -import org.eclipse.hawkbit.ui.distributions.event.SoftwareModuleTableEvent.SoftwareModuleComponentEvent; import org.springframework.beans.factory.annotation.Autowired; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; /** - * Implementation of software module Layout . + * Implementation of software module Layout */ @SpringComponent @ViewScope @@ -46,41 +42,9 @@ public class SwModuleTableLayout extends AbstractTableLayout { super.init(swModuleTableHeader, swModuleTable, swModuleDetails); } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * isShortCutKeysRequired() - */ @Override - protected boolean isShortCutKeysRequired() { - return true; + protected void publishEvent() { + // nothing to publish } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * getShortCutKeysHandler() - */ - @Override - protected Handler getShortCutKeysHandler() { - return new Handler() { - - private static final long serialVersionUID = 1L; - - @Override - public void handleAction(final Action action, final Object sender, final Object target) { - if (ACTION_CTRL_A.equals(action)) { - swModuleTable.selectAll(); - getEventBus().publish(this, new SoftwareModuleTableEvent(SoftwareModuleComponentEvent.SELECT_ALL)); - } - } - - @Override - public Action[] getActions(final Object target, final Object sender) { - return new Action[] { ACTION_CTRL_A }; - } - }; - } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java index 2cd34d3fa..fefbca972 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java @@ -11,12 +11,8 @@ package org.eclipse.hawkbit.ui.management.dstable; import javax.annotation.PostConstruct; import org.eclipse.hawkbit.ui.common.table.AbstractTableLayout; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent; -import org.eclipse.hawkbit.ui.distributions.event.DistributionSetTableEvent.DistributionTableComponentEvent; import org.springframework.beans.factory.annotation.Autowired; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; @@ -46,42 +42,9 @@ public class DistributionTableLayout extends AbstractTableLayout { super.init(dsTableHeader, dsTable, distributionDetails); } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * isShortCutKeysRequired() - */ @Override - protected boolean isShortCutKeysRequired() { - return true; + protected void publishEvent() { + // nothing to publish } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * getShortCutKeysHandler() - */ - @Override - protected Handler getShortCutKeysHandler() { - return new Handler() { - - private static final long serialVersionUID = 1L; - - @Override - public void handleAction(final Action action, final Object sender, final Object target) { - if (ACTION_CTRL_A.equals(action)) { - dsTable.selectAll(); - getEventBus().publish(this, - new DistributionSetTableEvent(DistributionTableComponentEvent.SELECT_ALL)); - } - } - - @Override - public Action[] getActions(final Object target, final Object sender) { - return new Action[] { ACTION_CTRL_A }; - } - }; - } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java index 4cfbeecf5..214d12106 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/event/TargetTableEvent.java @@ -22,7 +22,7 @@ public class TargetTableEvent extends BaseEntityEvent { * */ public enum TargetComponentEvent { - REFRESH_TARGETS, SELLECT_ALL, BULK_TARGET_CREATED, BULK_UPLOAD_COMPLETED, BULK_TARGET_UPLOAD_STARTED, BULK_UPLOAD_PROCESS_STARTED + REFRESH_TARGETS, SELECT_ALL, BULK_TARGET_CREATED, BULK_UPLOAD_COMPLETED, BULK_TARGET_UPLOAD_STARTED, BULK_UPLOAD_PROCESS_STARTED } private TargetComponentEvent targetComponentEvent; 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 ed6d033bd..fccee7cb5 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 @@ -95,7 +95,7 @@ public class CountMessageLabel extends Label { @EventBusListenerMethod(scope = EventScope.SESSION) void onEvent(final TargetTableEvent event) { - if (TargetTableEvent.TargetComponentEvent.SELLECT_ALL == event.getTargetComponentEvent() + if (TargetTableEvent.TargetComponentEvent.SELECT_ALL == event.getTargetComponentEvent() || TargetComponentEvent.REFRESH_TARGETS == event.getTargetComponentEvent()) { displayTargetCountStatus(); } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java index 2bd86868c..8c3ec3a1a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableLayout.java @@ -16,8 +16,6 @@ import org.eclipse.hawkbit.ui.management.event.TargetTableEvent.TargetComponentE import org.springframework.beans.factory.annotation.Autowired; import org.vaadin.spring.events.EventBus; -import com.vaadin.event.Action; -import com.vaadin.event.Action.Handler; import com.vaadin.spring.annotation.SpringComponent; import com.vaadin.spring.annotation.ViewScope; @@ -47,45 +45,14 @@ public class TargetTableLayout extends AbstractTableLayout { */ @PostConstruct void init() { + super.init(targetTableHeader, targetTable, targetDetails); } - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * isShortCutKeysRequired() - */ @Override - protected boolean isShortCutKeysRequired() { - return true; - } + protected void publishEvent() { - /* - * (non-Javadoc) - * - * @see org.eclipse.hawkbit.server.ui.common.table.AbstractTableLayout# - * getShortCutKeysHandler() - */ - @Override - protected Handler getShortCutKeysHandler() { - return new Handler() { - - private static final long serialVersionUID = 1L; - - @Override - public void handleAction(final Action action, final Object sender, final Object target) { - if (ACTION_CTRL_A.equals(action)) { - targetTable.selectAll(); - eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.SELLECT_ALL)); - } - } - - @Override - public Action[] getActions(final Object target, final Object sender) { - return new Action[] { ACTION_CTRL_A }; - } - }; + eventBus.publish(this, new TargetTableEvent(TargetComponentEvent.SELECT_ALL)); } } From 2b33f3646b5f221556a4af92a381292affe3f755 Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Tue, 14 Jun 2016 13:28:29 +0200 Subject: [PATCH 10/46] remove EventBus from AbstractTableLayout Signed-off-by: Melanie Retter --- .../hawkbit/ui/common/table/AbstractTableLayout.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java index b85006468..98874626d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java @@ -10,7 +10,6 @@ package org.eclipse.hawkbit.ui.common.table; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractTableDetailsLayout; import org.springframework.beans.factory.annotation.Autowired; -import org.vaadin.spring.events.EventBus; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; @@ -33,9 +32,6 @@ public abstract class AbstractTableLayout extends VerticalLayout { protected static final ShortcutAction ACTION_CTRL_A = new ShortcutAction("Select All", ShortcutAction.KeyCode.A, new int[] { ShortcutAction.ModifierKey.CTRL }); - @Autowired - private transient EventBus.SessionEventBus eventBus; - private AbstractTableHeader tableHeader; private AbstractTable table; @@ -128,8 +124,4 @@ public abstract class AbstractTableLayout extends VerticalLayout { tableHeader.setFilterButtonsIconVisible(visible); } - public EventBus.SessionEventBus getEventBus() { - return eventBus; - } - } From e35ef0f7db8f780c03045d6a60e69c386621a694 Mon Sep 17 00:00:00 2001 From: Melanie Retter Date: Tue, 14 Jun 2016 19:10:21 +0200 Subject: [PATCH 11/46] only select all rows if table is multiselect Signed-off-by: Melanie Retter --- .../org/eclipse/hawkbit/ui/common/table/AbstractTable.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 89e8be799..1121ac8a7 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 @@ -157,8 +157,10 @@ public abstract class AbstractTable extends Table { * Select all rows in the table. */ protected void selectAll() { - // only contains the ItemIds of the visible items in the table - setValue(getItemIds()); + if (isMultiSelect()) { + // only contains the ItemIds of the visible items in the table + setValue(getItemIds()); + } } private void setColumnProperties() { From ecd56474382d73ca9e628d916cefb5b93c06874b Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Wed, 15 Jun 2016 10:45:34 +0200 Subject: [PATCH 12/46] extends mgmt simulator. Extended scalabaility of dmf listener. Signed-off-by: Kai Zimmermann --- .../simulator/amqp/AmqpConfiguration.java | 45 +++++--- .../hawkbit/simulator/amqp/SenderService.java | 22 +++- .../simulator/amqp/SpReceiverService.java | 11 +- .../{logback.xml => logback-spring.xml} | 4 +- .../hawkbit/mgmt/client/Application.java | 9 +- .../client/ClientConfigurationProperties.java | 31 +++++ .../scenarios/ConfigurableScenario.java | 108 ++++++++++++++++-- .../src/main/resources/application.properties | 14 +-- .../{logback.xml => logback-spring.xml} | 0 .../hawkbit/amqp/AmqpConfiguration.java | 7 ++ .../eclipse/hawkbit/amqp/AmqpProperties.java | 15 ++- .../mgmt/rest/api/MgmtTargetRestApi.java | 83 +++++++------- .../mgmt/rest/resource/MgmtTargetMapper.java | 5 +- .../rest/resource/MgmtTargetResource.java | 66 +++++------ .../java/org/eclipse/hawkbit/util/IpUtil.java | 16 ++- 15 files changed, 315 insertions(+), 121 deletions(-) rename examples/hawkbit-device-simulator/src/main/resources/{logback.xml => logback-spring.xml} (94%) rename examples/hawkbit-example-mgmt-simulator/src/main/resources/{logback.xml => logback-spring.xml} (100%) 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 e954cec96..57d4762b0 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 @@ -12,6 +12,8 @@ import java.time.Duration; import java.util.HashMap; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.FanoutExchange; @@ -22,42 +24,53 @@ import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; -import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.beans.factory.annotation.Autowired; 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; /** * The spring AMQP configuration to use a AMQP for communication with SP update * server. - * - * - * */ @Configuration @EnableConfigurationProperties(AmqpProperties.class) public class AmqpConfiguration { + private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class); + @Autowired protected AmqpProperties amqpProperties; @Autowired private ConnectionFactory connectionFactory; - @Autowired - private RabbitTemplate rabbitTemplate; - /** - * Create jackson message converter bean. - * - * @return the jackson message converter + * @return {@link RabbitTemplate} with automatic retry, published confirms + * and {@link Jackson2JsonMessageConverter}. */ @Bean - public MessageConverter jsonMessageConverter() { - final Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter(); - rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter); - return jackson2JsonMessageConverter; + public RabbitTemplate rabbitTemplate() { + final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); + rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter()); + + final RetryTemplate retryTemplate = new RetryTemplate(); + retryTemplate.setBackOffPolicy(new ExponentialBackOffPolicy()); + rabbitTemplate.setRetryTemplate(retryTemplate); + + rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> { + if (ack) { + LOGGER.debug("Message with correlation ID {} confirmed by broker.", correlationData.getId()); + } else { + LOGGER.error("Broker is unable to handle message with correlation ID {} : {}", correlationData.getId(), + cause); + } + + }); + + return rabbitTemplate; } /** @@ -138,8 +151,8 @@ public class AmqpConfiguration { final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory(); containerFactory.setDefaultRequeueRejected(false); containerFactory.setConnectionFactory(connectionFactory); - containerFactory.setConcurrentConsumers(20); - containerFactory.setMaxConcurrentConsumers(20); + containerFactory.setConcurrentConsumers(3); + containerFactory.setMaxConcurrentConsumers(10); containerFactory.setPrefetchCount(20); return containerFactory; } 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 6ed6ff0cb..6f16ac736 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,9 +8,14 @@ */ package org.eclipse.hawkbit.simulator.amqp; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.rabbit.support.CorrelationData; import org.springframework.amqp.support.converter.AbstractJavaTypeMapper; import org.springframework.beans.factory.annotation.Autowired; @@ -22,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired; */ public abstract class SenderService extends MessageService { + private static final Logger LOGGER = LoggerFactory.getLogger(SenderService.class); + /** * Constructor for sender service. * @@ -40,18 +47,25 @@ public abstract class SenderService extends MessageService { /** * Send a message if the message is not null. * - * @param adress + * @param address * the exchange name * @param message * the amqp message which will be send if its not null */ - public void sendMessage(final String adress, final Message message) { + public void sendMessage(final String address, final Message message) { if (message == null) { return; } message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME); - rabbitTemplate.setExchange(adress); - rabbitTemplate.send(message); + final String correlationId = UUID.randomUUID().toString(); + + if (LOGGER.isTraceEnabled()) { + LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, address, correlationId); + } else { + LOGGER.debug("Sending message to exchange {} with correlationId {}", address, correlationId); + } + + rabbitTemplate.send(address, null, message, new CorrelationData(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 e06b2baf3..4f2981be1 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 @@ -35,14 +35,21 @@ import com.google.common.collect.Lists; public class SpReceiverService extends ReceiverService { private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class); - public static final String SOFTWARE_MODULE_FIRMWARE = "firmware"; - private final SpSenderService spSenderService; private final DeviceSimulatorUpdater deviceUpdater; /** * Constructor. + * + * @param rabbitTemplate + * for sending messages + * @param amqpProperties + * for amqp configuration + * @param spSenderService + * to send messages + * @param deviceUpdater + * simulator service for updates */ @Autowired public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties, diff --git a/examples/hawkbit-device-simulator/src/main/resources/logback.xml b/examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml similarity index 94% rename from examples/hawkbit-device-simulator/src/main/resources/logback.xml rename to examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml index 469c7bde3..f25a61cd1 100644 --- a/examples/hawkbit-device-simulator/src/main/resources/logback.xml +++ b/examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml @@ -19,7 +19,9 @@ - + + + diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java index 036c19ed1..e89f3211b 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java @@ -48,7 +48,7 @@ public class Application implements CommandLineRunner { private ClientConfigurationProperties configuration; @Autowired - private ConfigurableScenario configurableScenario; + private ConfigurableScenario configuredScenario; @Autowired private CreateStartedRolloutExample gettingStartedRolloutScenario; @@ -63,9 +63,8 @@ public class Application implements CommandLineRunner { // run the create and start rollout example gettingStartedRolloutScenario.run(); } else { - // run the getting started scenario which creates a setup of - // distribution set and software modules to be used - configurableScenario.run(); + // run the configured scenario from properties + configuredScenario.run(); } } @@ -107,4 +106,4 @@ public class Application implements CommandLineRunner { } return false; } -} \ No newline at end of file +} diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java index cc5fe27e9..8a5c61575 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java @@ -39,8 +39,13 @@ public class ClientConfigurationProperties { private final List scenarios = new ArrayList<>(); + /** + * Simulation {@link Scenario}. + * + */ public static class Scenario { private String tenant = "DEFAULT"; + private boolean cleanRepository; private int targets = 100; private int distributionSets = 10; private int appModulesPerDistributionSet = 2; @@ -50,6 +55,8 @@ public class ClientConfigurationProperties { private String targetName = "Device"; private int artifactsPerSM = 1; private String targetAddress = "amqp:/simulator.replyTo"; + private boolean runRollouts = true; + private int rolloutDeploymentGroups = 4; /** * Artifact size. Values can use the suffixed "MB" or "KB" to indicate a @@ -57,6 +64,30 @@ public class ClientConfigurationProperties { */ private String artifactSize = "1MB"; + public boolean isCleanRepository() { + return cleanRepository; + } + + public void setCleanRepository(final boolean cleanRepository) { + this.cleanRepository = cleanRepository; + } + + public int getRolloutDeploymentGroups() { + return rolloutDeploymentGroups; + } + + public void setRolloutDeploymentGroups(final int rolloutDeploymentGroups) { + this.rolloutDeploymentGroups = rolloutDeploymentGroups; + } + + public boolean isRunRollouts() { + return runRollouts; + } + + public void setRunRollouts(final boolean runRollouts) { + this.runRollouts = runRollouts; + } + public String getTargetAddress() { return targetAddress; } diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java index 60144a88e..84b3da6ee 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2015 Bosch Software Innovations GmbH and others. +x * 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 @@ -10,20 +10,25 @@ package org.eclipse.hawkbit.mgmt.client.scenarios; import java.util.List; import java.util.Random; +import java.util.concurrent.TimeUnit; import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties; import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties.Scenario; import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtRolloutClientResource; import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; -import org.eclipse.hawkbit.mgmt.client.resource.MgmtSystemManagementClientResource; import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource; import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder; +import org.eclipse.hawkbit.mgmt.client.resource.builder.RolloutBuilder; import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder; import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder; import org.eclipse.hawkbit.mgmt.client.resource.builder.TargetBuilder; import org.eclipse.hawkbit.mgmt.client.scenarios.upload.ArtifactFile; +import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; +import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; +import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -53,7 +58,7 @@ public class ConfigurableScenario { private MgmtTargetClientResource targetResource; @Autowired - private MgmtSystemManagementClientResource systemManagementResource; + private MgmtRolloutClientResource rolloutResource; @Autowired private ClientConfigurationProperties clientConfigurationProperties; @@ -65,16 +70,93 @@ public class ConfigurableScenario { LOGGER.info("Running Configurable Scenario..."); - clientConfigurationProperties.getScenarios().parallelStream().forEach(this::createScenario); + clientConfigurationProperties.getScenarios().forEach(this::createScenario); } private void createScenario(final Scenario scenario) { - systemManagementResource.deleteTenant(scenario.getTenant()); + if (scenario.isCleanRepository()) { + cleanRepository(); + } + createTargets(scenario); createDistributionSets(scenario); + + if (scenario.isRunRollouts()) { + runRollouts(scenario); + } + } + + private void cleanRepository() { + LOGGER.info("Cleaning repository"); + deleteTargets(); + deleteRollouts(); + deleteDistributionSets(); + deleteSoftwareModules(); + LOGGER.info("Cleaning repository -> Done"); + } + + private void deleteRollouts() { + // TODO: complete this as soon as rollouts can be deleted + + } + + private void deleteSoftwareModules() { + PagedList modules; + do { + modules = softwareModuleResource.getSoftwareModules(0, 100, null, null).getBody(); + modules.getContent().forEach(module -> softwareModuleResource.deleteSoftwareModule(module.getModuleId())); + } while (modules.getTotal() > 100); + } + + private void deleteDistributionSets() { + PagedList distributionSets; + do { + distributionSets = distributionSetResource.getDistributionSets(0, 100, null, null).getBody(); + distributionSets.getContent().forEach(set -> distributionSetResource.deleteDistributionSet(set.getDsId())); + } while (distributionSets.getTotal() > 100); + } + + private void deleteTargets() { + PagedList targets; + do { + targets = targetResource.getTargets(0, 100, null, null).getBody(); + targets.getContent().forEach(target -> targetResource.deleteTarget(target.getControllerId())); + } while (targets.getTotal() > 100); + } + + private void runRollouts(final Scenario scenario) { + distributionSetResource.getDistributionSets(0, scenario.getDistributionSets(), null, null).getBody() + .getContent().forEach(set -> runRollout(set, scenario)); + + } + + private void runRollout(final MgmtDistributionSet set, final Scenario scenario) { + LOGGER.info("Run rollout for set {}", set.getDsId()); + // create a Rollout + final MgmtRolloutResponseBody rolloutResponseBody = rolloutResource + .create(new RolloutBuilder().name("Rollout" + set.getName() + set.getVersion()) + .groupSize(scenario.getRolloutDeploymentGroups()).targetFilterQuery("name==*") + .distributionSetId(set.getDsId()).successThreshold("80").errorThreshold("5").build()) + .getBody(); + + // start the created Rollout + rolloutResource.start(rolloutResponseBody.getRolloutId(), true); + + // wait until rollout is complete + do { + try { + TimeUnit.SECONDS.sleep(35); + } catch (final InterruptedException e) { + LOGGER.warn("Interrupted!"); + Thread.currentThread().interrupt(); + } + } while (targetResource.getTargets(0, 1, null, "updateStatus==IN_SYNC").getBody().getTotal() < scenario + .getTargets()); + LOGGER.info("Run rollout for set {} -> Done", set.getDsId()); } private void createDistributionSets(final Scenario scenario) { + LOGGER.info("Creating {} distribution sets", scenario.getDistributionSets()); final byte[] artifact = generateArtifact(scenario); distributionSetResource @@ -87,6 +169,8 @@ public class ConfigurableScenario { modules.forEach(module -> assign.id(module.getModuleId())); distributionSetResource.assignSoftwareModules(dsSet.getDsId(), assign.build()); }); + + LOGGER.info("Creating {} distribution sets -> Done", scenario.getDistributionSets()); } private List addModules(final Scenario scenario, final MgmtDistributionSet dsSet, @@ -110,8 +194,10 @@ public class ConfigurableScenario { return modules; } - private byte[] generateArtifact(final Scenario scenario) { - // create random object + private static byte[] generateArtifact(final Scenario scenario) { + + // Exception squid:S2245 - not used for cryptographic function + @SuppressWarnings("squid:S2245") final Random random = new Random(); // create byte array @@ -124,14 +210,18 @@ public class ConfigurableScenario { } private void createTargets(final Scenario scenario) { + LOGGER.info("Creating {} targets", scenario.getTargets()); + for (int i = 0; i < scenario.getTargets() / 100; i++) { targetResource.createTargets(new TargetBuilder().controllerId(scenario.getTargetName()) .address(scenario.getTargetAddress()).buildAsList(i * 100, - (i + 1) * 100 > scenario.getTargets() ? scenario.getTargets() - i * 100 : 100)); + (i + 1) * 100 > scenario.getTargets() ? (scenario.getTargets() - (i * 100)) : 100)); } + + LOGGER.info("Creating {} targets -> Done", scenario.getTargets()); } - private int parseSize(final String s) { + private static int parseSize(final String s) { final String size = s.toUpperCase(); if (size.endsWith("KB")) { return Integer.valueOf(size.substring(0, size.length() - 2)) * 1024; diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties index f538bb1cb..e19b83e19 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties +++ b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties @@ -13,12 +13,8 @@ hawkbit.password=admin spring.main.show-banner=false -#hawkbit.scenarios.[0].targets=0 -#hawkbit.scenarios.[0].ds-name=gettingstarted-example -#hawkbit.scenarios.[0].distribution-sets=3 -#hawkbit.scenarios.[0].sm-fw-name=gettingstarted-example -#hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example - -hawkbit.scenarios.[0].targets=10000 -hawkbit.scenarios.[0].distribution-sets=100 -hawkbit.scenarios.[0].artifactsPerSM=0 \ No newline at end of file +hawkbit.scenarios.[0].targets=0 +hawkbit.scenarios.[0].ds-name=gettingstarted-example +hawkbit.scenarios.[0].distribution-sets=3 +hawkbit.scenarios.[0].sm-fw-name=gettingstarted-example +hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example \ No newline at end of file diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback.xml b/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml similarity index 100% rename from examples/hawkbit-example-mgmt-simulator/src/main/resources/logback.xml rename to examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml 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 541ae414c..3fbc6aee2 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 @@ -32,6 +32,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.TaskExecutor; import org.springframework.retry.backoff.ExponentialBackOffPolicy; import org.springframework.retry.support.RetryTemplate;; @@ -58,6 +59,9 @@ public class AmqpConfiguration { @Autowired private ConnectionFactory rabbitConnectionFactory; + @Autowired + private TaskExecutor taskExecutor; + @Configuration protected static class RabbitConnectionFactoryCreator { @@ -240,6 +244,9 @@ public class AmqpConfiguration { containerFactory.setDefaultRequeueRejected(false); containerFactory.setConnectionFactory(rabbitConnectionFactory); containerFactory.setMissingQueuesFatal(amqpProperties.isMissingQueuesFatal()); + containerFactory.setTaskExecutor(taskExecutor); + containerFactory.setConcurrentConsumers(3); + containerFactory.setMaxConcurrentConsumers(amqpProperties.getMaxConcurrentConsumers()); return containerFactory; } diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java index f9b4cceb6..a20c59792 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java @@ -38,13 +38,26 @@ public class AmqpProperties { /** * Missing queue fatal. */ - private boolean missingQueuesFatal = false; + private boolean missingQueuesFatal; /** * Requested heartbeat interval from broker in {@link TimeUnit#SECONDS}. */ private int requestedHeartBeat = (int) TimeUnit.SECONDS.toSeconds(60); + /** + * Sets an upper limit to the number of consumers. + */ + private int maxConcurrentConsumers = 10; + + public int getMaxConcurrentConsumers() { + return maxConcurrentConsumers; + } + + public void setMaxConcurrentConsumers(final int maxConcurrentConsumers) { + this.maxConcurrentConsumers = maxConcurrentConsumers; + } + /** * Is missingQueuesFatal enabled * diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java index bf4e169a0..97a0eae5c 100644 --- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java +++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/rest/api/MgmtTargetRestApi.java @@ -35,14 +35,14 @@ public interface MgmtTargetRestApi { /** * Handles the GET request of retrieving a single target. * - * @param targetId + * @param controllerId * the ID of the target to retrieve * @return a single target with status OK. */ - @RequestMapping(method = RequestMethod.GET, value = "/{targetId}", produces = { "application/hal+json", + @RequestMapping(method = RequestMethod.GET, value = "/{controllerId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity getTarget(@PathVariable("targetId") final String targetId); + ResponseEntity getTarget(@PathVariable("controllerId") final String controllerId); /** * Handles the GET request of retrieving all targets. @@ -91,7 +91,7 @@ public interface MgmtTargetRestApi { * path of the request. A given ID in the request body is ignored. It's not * possible to set fields to {@code null} values. * - * @param targetId + * @param controllerId * the path parameter which contains the ID of the target * @param targetRest * the request body which contains the fields which should be @@ -100,40 +100,40 @@ public interface MgmtTargetRestApi { * @return the updated target response which contains all fields also fields * which have not updated */ - @RequestMapping(method = RequestMethod.PUT, value = "/{targetId}", consumes = { "application/hal+json", + @RequestMapping(method = RequestMethod.PUT, value = "/{controllerId}", consumes = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity updateTarget(@PathVariable("targetId") final String targetId, + ResponseEntity updateTarget(@PathVariable("controllerId") final String controllerId, @RequestBody final MgmtTargetRequestBody targetRest); /** * Handles the DELETE request of deleting a target. * - * @param targetId + * @param controllerId * the ID of the target to be deleted - * @return If the given targetId could exists and could be deleted Http OK. - * In any failure the JsonResponseExceptionHandler is handling the - * response. + * @return If the given controllerId could exists and could be deleted Http + * OK. In any failure the JsonResponseExceptionHandler is handling + * the response. */ - @RequestMapping(method = RequestMethod.DELETE, value = "/{targetId}", produces = { "application/hal+json", + @RequestMapping(method = RequestMethod.DELETE, value = "/{controllerId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity deleteTarget(@PathVariable("targetId") final String targetId); + ResponseEntity deleteTarget(@PathVariable("controllerId") final String controllerId); /** * Handles the GET request of retrieving the attributes of a specific * target. * - * @param targetId + * @param controllerId * the ID of the target to retrieve the attributes. * @return the target attributes as map response with status OK */ - @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/attributes", produces = { "application/hal+json", - MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity getAttributes(@PathVariable("targetId") final String targetId); + @RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/attributes", produces = { + "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) + ResponseEntity getAttributes(@PathVariable("controllerId") final String controllerId); /** * Handles the GET request of retrieving the Actions of a specific target. * - * @param targetId + * @param controllerId * to load actions for * @param pagingOffsetParam * the offset of list of targets for pagination, might not be @@ -151,9 +151,9 @@ public interface MgmtTargetRestApi { * status OK. The response is always paged. In any failure the * JsonResponseExceptionHandler is handling the response. */ - @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions", produces = { "application/hal+json", + @RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/actions", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity> getActionHistory(@PathVariable("targetId") final String targetId, + ResponseEntity> getActionHistory(@PathVariable("controllerId") final String controllerId, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam, @@ -163,22 +163,22 @@ public interface MgmtTargetRestApi { * Handles the GET request of retrieving a specific Actions of a specific * Target. * - * @param targetId + * @param controllerId * to load the action for * @param actionId * to load * @return the action */ - @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions/{actionId}", produces = { + @RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/actions/{actionId}", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity getAction(@PathVariable("targetId") final String targetId, + ResponseEntity getAction(@PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId); /** * Handles the DELETE request of canceling an specific Actions of a specific * Target. * - * @param targetId + * @param controllerId * the ID of the target in the URL path parameter * @param actionId * the ID of the action in the URL path parameter @@ -186,8 +186,8 @@ public interface MgmtTargetRestApi { * optional parameter, which indicates a force cancel * @return status no content in case cancellation was successful */ - @RequestMapping(method = RequestMethod.DELETE, value = "/{targetId}/actions/{actionId}") - ResponseEntity cancelAction(@PathVariable("targetId") final String targetId, + @RequestMapping(method = RequestMethod.DELETE, value = "/{controllerId}/actions/{actionId}") + ResponseEntity cancelAction(@PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId, @RequestParam(value = "force", required = false, defaultValue = "false") final boolean force); @@ -195,7 +195,7 @@ public interface MgmtTargetRestApi { * Handles the GET request of retrieving the ActionStatus of a specific * target and action. * - * @param targetId + * @param controllerId * of the the action * @param actionId * of the status we are intend to load @@ -212,10 +212,10 @@ public interface MgmtTargetRestApi { * with status OK. The response is always paged. In any failure the * JsonResponseExceptionHandler is handling the response. */ - @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/actions/{actionId}/status", produces = { + @RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/actions/{actionId}/status", produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity> getActionStatusList(@PathVariable("targetId") final String targetId, - @PathVariable("actionId") final Long actionId, + ResponseEntity> getActionStatusList( + @PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam); @@ -224,40 +224,43 @@ public interface MgmtTargetRestApi { * Handles the GET request of retrieving the assigned distribution set of an * specific target. * - * @param targetId + * @param controllerId * the ID of the target to retrieve the assigned distribution * @return the assigned distribution set with status OK, if none is assigned * than {@code null} content (e.g. "{}") */ - @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/assignedDS", produces = { "application/hal+json", - MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity getAssignedDistributionSet(@PathVariable("targetId") final String targetId); + @RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/assignedDS", produces = { + "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) + ResponseEntity getAssignedDistributionSet( + @PathVariable("controllerId") final String controllerId); /** * Changes the assigned distribution set of a target. * - * @param targetId + * @param controllerId * of the target to change * @param dsId * of the distributionset that is to be assigned * @return http status */ - @RequestMapping(method = RequestMethod.POST, value = "/{targetId}/assignedDS", consumes = { "application/hal+json", + @RequestMapping(method = RequestMethod.POST, value = "/{controllerId}/assignedDS", consumes = { + "application/hal+json", MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity postAssignedDistributionSet(@PathVariable("targetId") final String targetId, + ResponseEntity postAssignedDistributionSet(@PathVariable("controllerId") final String controllerId, @RequestBody final MgmtDistributionSetAssigment dsId); /** * Handles the GET request of retrieving the installed distribution set of * an specific target. * - * @param targetId + * @param controllerId * the ID of the target to retrieve * @return the assigned installed set with status OK, if none is installed * than {@code null} content (e.g. "{}") */ - @RequestMapping(method = RequestMethod.GET, value = "/{targetId}/installedDS", produces = { "application/hal+json", - MediaType.APPLICATION_JSON_VALUE }) - ResponseEntity getInstalledDistributionSet(@PathVariable("targetId") final String targetId); + @RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/installedDS", produces = { + "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) + ResponseEntity getInstalledDistributionSet( + @PathVariable("controllerId") final String controllerId); } diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java index d77cbaa53..f6cf9f54b 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java @@ -32,6 +32,7 @@ import org.eclipse.hawkbit.repository.model.PollStatus; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.rest.data.SortDirection; +import org.eclipse.hawkbit.util.IpUtil; /** * A mapper which maps repository model to RESTful model representation and @@ -141,7 +142,9 @@ public final class MgmtTargetMapper { final URI address = target.getTargetInfo().getAddress(); if (address != null) { - targetRest.setIpAddress(address.getHost()); + if (IpUtil.isIpAddresKnown(address)) { + targetRest.setIpAddress(address.getHost()); + } targetRest.setAddress(address.toString()); } diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java index cc7bbcde6..c41dadd27 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetResource.java @@ -68,8 +68,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi { private EntityFactory entityFactory; @Override - public ResponseEntity getTarget(@PathVariable("targetId") final String targetId) { - final Target findTarget = findTargetWithExceptionIfNotFound(targetId); + public ResponseEntity getTarget(@PathVariable("controllerId") final String controllerId) { + final Target findTarget = findTargetWithExceptionIfNotFound(controllerId); // to single response include poll status final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget); MgmtTargetMapper.addPollStatus(findTarget, response); @@ -115,9 +115,9 @@ public class MgmtTargetResource implements MgmtTargetRestApi { } @Override - public ResponseEntity updateTarget(@PathVariable("targetId") final String targetId, + public ResponseEntity updateTarget(@PathVariable("controllerId") final String controllerId, @RequestBody final MgmtTargetRequestBody targetRest) { - final Target existingTarget = findTargetWithExceptionIfNotFound(targetId); + final Target existingTarget = findTargetWithExceptionIfNotFound(controllerId); LOG.debug("updating target {}", existingTarget.getId()); if (targetRest.getDescription() != null) { existingTarget.setDescription(targetRest.getDescription()); @@ -131,16 +131,16 @@ public class MgmtTargetResource implements MgmtTargetRestApi { } @Override - public ResponseEntity deleteTarget(@PathVariable("targetId") final String targetId) { - final Target target = findTargetWithExceptionIfNotFound(targetId); + public ResponseEntity deleteTarget(@PathVariable("controllerId") final String controllerId) { + final Target target = findTargetWithExceptionIfNotFound(controllerId); this.targetManagement.deleteTargets(target.getId()); - LOG.debug("{} target deleted, return status {}", targetId, HttpStatus.OK); + LOG.debug("{} target deleted, return status {}", controllerId, HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK); } @Override - public ResponseEntity getAttributes(@PathVariable("targetId") final String targetId) { - final Target foundTarget = findTargetWithExceptionIfNotFound(targetId); + public ResponseEntity getAttributes(@PathVariable("controllerId") final String controllerId) { + final Target foundTarget = findTargetWithExceptionIfNotFound(controllerId); final Map controllerAttributes = foundTarget.getTargetInfo().getControllerAttributes(); if (controllerAttributes.isEmpty()) { return new ResponseEntity<>(HttpStatus.NO_CONTENT); @@ -153,13 +153,14 @@ public class MgmtTargetResource implements MgmtTargetRestApi { } @Override - public ResponseEntity> getActionHistory(@PathVariable("targetId") final String targetId, + public ResponseEntity> getActionHistory( + @PathVariable("controllerId") final String controllerId, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) final String rsqlParam) { - final Target foundTarget = findTargetWithExceptionIfNotFound(targetId); + final Target foundTarget = findTargetWithExceptionIfNotFound(controllerId); final int sanitizedOffsetParam = PagingUtility.sanitizeOffsetParam(pagingOffsetParam); final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam); @@ -177,14 +178,15 @@ public class MgmtTargetResource implements MgmtTargetRestApi { } return new ResponseEntity<>( - new PagedList<>(MgmtTargetMapper.toResponse(targetId, activeActions.getContent()), totalActionCount), + new PagedList<>(MgmtTargetMapper.toResponse(controllerId, activeActions.getContent()), + totalActionCount), HttpStatus.OK); } @Override - public ResponseEntity getAction(@PathVariable("targetId") final String targetId, + public ResponseEntity getAction(@PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId) { - final Target target = findTargetWithExceptionIfNotFound(targetId); + final Target target = findTargetWithExceptionIfNotFound(controllerId); final Action action = findActionWithExceptionIfNotFound(actionId); if (!action.getTarget().getId().equals(target.getId())) { @@ -192,18 +194,18 @@ public class MgmtTargetResource implements MgmtTargetRestApi { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - final MgmtAction result = MgmtTargetMapper.toResponse(targetId, action, action.isActive()); + final MgmtAction result = MgmtTargetMapper.toResponse(controllerId, action, action.isActive()); if (!action.isCancelingOrCanceled()) { result.add(linkTo( methodOn(MgmtDistributionSetRestApi.class).getDistributionSet(action.getDistributionSet().getId())) .withRel("distributionset")); } else if (action.isCancelingOrCanceled()) { - result.add(linkTo(methodOn(MgmtTargetRestApi.class).getAction(targetId, action.getId())) + result.add(linkTo(methodOn(MgmtTargetRestApi.class).getAction(controllerId, action.getId())) .withRel(MgmtRestConstants.TARGET_V1_CANCELED_ACTION)); } - result.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionStatusList(targetId, action.getId(), 0, + result.add(linkTo(methodOn(MgmtTargetRestApi.class).getActionStatusList(controllerId, action.getId(), 0, MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE, ActionStatusFields.ID.getFieldName() + ":" + SortDirection.DESC)) .withRel(MgmtRestConstants.TARGET_V1_ACTION_STATUS)); @@ -212,10 +214,10 @@ public class MgmtTargetResource implements MgmtTargetRestApi { } @Override - public ResponseEntity cancelAction(@PathVariable("targetId") final String targetId, + public ResponseEntity cancelAction(@PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId, @RequestParam(value = "force", required = false, defaultValue = "false") final boolean force) { - final Target target = findTargetWithExceptionIfNotFound(targetId); + final Target target = findTargetWithExceptionIfNotFound(controllerId); final Action action = findActionWithExceptionIfNotFound(actionId); if (force) { @@ -231,12 +233,12 @@ public class MgmtTargetResource implements MgmtTargetRestApi { @Override public ResponseEntity> getActionStatusList( - @PathVariable("targetId") final String targetId, @PathVariable("actionId") final Long actionId, + @PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) final int pagingOffsetParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) final int pagingLimitParam, @RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) final String sortParam) { - final Target target = findTargetWithExceptionIfNotFound(targetId); + final Target target = findTargetWithExceptionIfNotFound(controllerId); final Action action = findActionWithExceptionIfNotFound(actionId); if (!action.getTarget().getId().equals(target.getId())) { @@ -260,8 +262,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi { @Override public ResponseEntity getAssignedDistributionSet( - @PathVariable("targetId") final String targetId) { - final Target findTarget = findTargetWithExceptionIfNotFound(targetId); + @PathVariable("controllerId") final String controllerId) { + final Target findTarget = findTargetWithExceptionIfNotFound(controllerId); final MgmtDistributionSet distributionSetRest = MgmtDistributionSetMapper .toResponse(findTarget.getAssignedDistributionSet()); final HttpStatus retStatus; @@ -274,29 +276,29 @@ public class MgmtTargetResource implements MgmtTargetRestApi { } @Override - public ResponseEntity postAssignedDistributionSet(@PathVariable("targetId") final String targetId, + public ResponseEntity postAssignedDistributionSet(@PathVariable("controllerId") final String controllerId, @RequestBody final MgmtDistributionSetAssigment dsId) { - findTargetWithExceptionIfNotFound(targetId); + findTargetWithExceptionIfNotFound(controllerId); final ActionType type = (dsId.getType() != null) ? MgmtRestModelMapper.convertActionType(dsId.getType()) : ActionType.FORCED; final Iterator changed = this.deploymentManagement - .assignDistributionSet(dsId.getId(), type, dsId.getForcetime(), targetId).getAssignedEntity() + .assignDistributionSet(dsId.getId(), type, dsId.getForcetime(), controllerId).getAssignedEntity() .iterator(); if (changed.hasNext()) { return new ResponseEntity<>(HttpStatus.OK); } LOG.error("Target update (ds {} assigment to target {}) failed! Returnd target list is empty.", dsId.getId(), - targetId); + controllerId); return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } @Override public ResponseEntity getInstalledDistributionSet( - @PathVariable("targetId") final String targetId) { - final Target findTarget = findTargetWithExceptionIfNotFound(targetId); + @PathVariable("controllerId") final String controllerId) { + final Target findTarget = findTargetWithExceptionIfNotFound(controllerId); final MgmtDistributionSet distributionSetRest = MgmtDistributionSetMapper .toResponse(findTarget.getTargetInfo().getInstalledDistributionSet()); final HttpStatus retStatus; @@ -308,10 +310,10 @@ public class MgmtTargetResource implements MgmtTargetRestApi { return new ResponseEntity<>(distributionSetRest, retStatus); } - private Target findTargetWithExceptionIfNotFound(final String targetId) { - final Target findTarget = this.targetManagement.findTargetByControllerID(targetId); + private Target findTargetWithExceptionIfNotFound(final String controllerId) { + final Target findTarget = this.targetManagement.findTargetByControllerID(controllerId); if (findTarget == null) { - throw new EntityNotFoundException("Target with Id {" + targetId + "} does not exist"); + throw new EntityNotFoundException("Target with Id {" + controllerId + "} does not exist"); } return findTarget; } diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java index 96fc557aa..c7778f776 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/IpUtil.java @@ -26,6 +26,7 @@ import com.google.common.net.HttpHeaders; */ public final class IpUtil { + private static final String HIDDEN_IP = "***"; private static final String SCHEME_SEPERATOR = "://"; private static final String HTTP_SCHEME = "http"; private static final String AMPQP_SCHEME = "amqp"; @@ -87,7 +88,7 @@ public final class IpUtil { ip = request.getRemoteAddr(); } } else { - ip = "***"; + ip = HIDDEN_IP; } return createHttpUri(ip); @@ -178,4 +179,17 @@ public final class IpUtil { public static boolean isAmqpUri(final URI uri) { return uri != null && AMPQP_SCHEME.equals(uri.getScheme()); } + + /** + * Check if the IP address of that {@link URI} is known, i.e. not an AQMP + * exchange in DMF case and not HIDDEN_IP in DDI case. + * + * @param uri + * the uri + * @return true if IP address is actually known by the server + */ + public static boolean isIpAddresKnown(final URI uri) { + return uri != null && !(AMPQP_SCHEME.equals(uri.getScheme()) || HIDDEN_IP.equals(uri.getHost())); + } + } From c3d04a530f03afbec2e29fc2bd849d3febb98965 Mon Sep 17 00:00:00 2001 From: Jonathan Knoblauch Date: Wed, 15 Jun 2016 13:45:50 +0200 Subject: [PATCH 13/46] Changed f to F --- .../hawkbit/ui/management/targettable/TargetTableHeader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java index 5b0aa285a..16dc584ed 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/targettable/TargetTableHeader.java @@ -398,7 +398,7 @@ public class TargetTableHeader extends AbstractTableHeader { getFilterDroppedInfo().setSizeFull(); getFilterDroppedInfo().addComponent(filteredDistLabel); getFilterDroppedInfo().addComponent(filterLabelClose); - getFilterDroppedInfo().setExpandRatio(filteredDistLabel, 1.0f); + getFilterDroppedInfo().setExpandRatio(filteredDistLabel, 1.0F); eventbus.publish(this, TargetFilterEvent.FILTER_BY_DISTRIBUTION); } From 20ebbed27f773235ea41c778d5f7dfac1c3ec42d Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Fri, 17 Jun 2016 11:32:04 +0200 Subject: [PATCH 14/46] Set separate handling for invalid message handling and internal server errors which should result in requeue instead of reject Signed-off-by: kaizimmerm --- .../org/eclipse/hawkbit/simulator/amqp/AmqpConfiguration.java | 2 +- .../org/eclipse/hawkbit/simulator/amqp/ReceiverService.java | 3 ++- .../main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java | 2 +- .../main/java/org/eclipse/hawkbit/amqp/BaseAmqpService.java | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) 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 57d4762b0..8ae2d87bd 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 @@ -149,7 +149,7 @@ public class AmqpConfiguration { @Bean(name = { "listenerContainerFactory" }) public SimpleRabbitListenerContainerFactory listenerContainerFactory() { final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory(); - containerFactory.setDefaultRequeueRejected(false); + containerFactory.setDefaultRequeueRejected(true); containerFactory.setConnectionFactory(connectionFactory); containerFactory.setConcurrentConsumers(3); containerFactory.setMaxConcurrentConsumers(10); diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java index f5c02789e..2e8833bab 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/ReceiverService.java @@ -8,6 +8,7 @@ */ package org.eclipse.hawkbit.simulator.amqp; +import org.springframework.amqp.AmqpRejectAndDontRequeueException; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.rabbit.core.RabbitTemplate; @@ -55,7 +56,7 @@ public abstract class ReceiverService extends MessageService { if (contentType != null && contentType.contains("json")) { return; } - throw new IllegalArgumentException("Content-Type is not JSON compatible"); + throw new AmqpRejectAndDontRequeueException("Content-Type is not JSON compatible"); } } 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 3fbc6aee2..9435e8860 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 @@ -241,7 +241,7 @@ public class AmqpConfiguration { @Bean(name = { "listenerContainerFactory" }) public SimpleRabbitListenerContainerFactory listenerContainerFactory() { final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory(); - containerFactory.setDefaultRequeueRejected(false); + containerFactory.setDefaultRequeueRejected(true); containerFactory.setConnectionFactory(rabbitConnectionFactory); containerFactory.setMissingQueuesFatal(amqpProperties.isMissingQueuesFatal()); containerFactory.setTaskExecutor(taskExecutor); 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 2c8feda13..88c88f264 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 @@ -15,6 +15,7 @@ import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.amqp.AmqpRejectAndDontRequeueException; import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.support.converter.AbstractJavaTypeMapper; @@ -110,7 +111,7 @@ public class BaseAmqpService { protected final void logAndThrowMessageError(final Message message, final String error) { LOGGER.warn("Warning! \"{}\" reported by message: {}", error, message); - throw new IllegalArgumentException(error); + throw new AmqpRejectAndDontRequeueException(error); } protected RabbitTemplate getRabbitTemplate() { From 58b883d773a4da83d76a18ed0eb1f35982b6bc82 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Sun, 19 Jun 2016 20:42:23 +0200 Subject: [PATCH 15/46] Added polling for DMF simulated devices. Signed-off-by: kaizimmerm --- examples/hawkbit-device-simulator/pom.xml | 24 ++---------- .../simulator/AbstractSimulatedDevice.java | 17 ++++++++- .../hawkbit/simulator/DDISimulatedDevice.java | 10 +---- .../hawkbit/simulator/DMFSimulatedDevice.java | 14 ++++++- .../simulator/DeviceSimulatorRepository.java | 4 +- .../simulator/NextPollTimeController.java | 12 +++--- .../simulator/SimulatedDeviceFactory.java | 8 +++- .../simulator/SimulationController.java | 2 +- .../simulator/SimulationProperties.java | 5 ++- .../simulator/amqp/AmqpConfiguration.java | 38 +++++++++++++++++++ .../event/NextPollCounterUpdate.java | 8 ++-- .../hawkbit/simulator/ui/SimulatorView.java | 4 +- .../src/main/resources/application.properties | 1 - .../{logback-spring.xml => logback.xml} | 5 --- 14 files changed, 94 insertions(+), 58 deletions(-) rename examples/hawkbit-device-simulator/src/main/resources/{logback-spring.xml => logback.xml} (86%) diff --git a/examples/hawkbit-device-simulator/pom.xml b/examples/hawkbit-device-simulator/pom.xml index 3c3df9486..035bcebfc 100644 --- a/examples/hawkbit-device-simulator/pom.xml +++ b/examples/hawkbit-device-simulator/pom.xml @@ -71,6 +71,10 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-logging + org.springframework.security spring-security-web @@ -83,26 +87,6 @@ org.springframework.boot spring-boot-starter - - - org.apache.logging.log4j - log4j-api - - - - org.slf4j - jul-to-slf4j - - - - org.slf4j - jcl-over-slf4j - - - - org.slf4j - log4j-over-slf4j - com.vaadin vaadin-spring-boot-starter diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java index 890f43367..c70d4f584 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java @@ -27,7 +27,7 @@ public abstract class AbstractSimulatedDevice { private UpdateStatus updateStatus = new UpdateStatus(ResponseStatus.SUCCESSFUL, "Simulation complete!"); private Protocol protocol = Protocol.DMF_AMQP; private String targetSecurityToken; - + private int pollDelaySec; private int nextPollCounterSec; /** @@ -84,13 +84,26 @@ public abstract class AbstractSimulatedDevice { * the ID of the simulated device * @param tenant * the tenant of the simulated device + * @param int + * pollDelaySec */ - AbstractSimulatedDevice(final String id, final String tenant, final Protocol protocol) { + AbstractSimulatedDevice(final String id, final String tenant, final Protocol protocol, final int pollDelaySec) { this.id = id; this.tenant = tenant; this.status = Status.UNKNWON; this.progress = 0.0; this.protocol = protocol; + this.pollDelaySec = pollDelaySec; + } + + abstract public void poll(); + + public int getPollDelaySec() { + return pollDelaySec; + } + + public void setPollDelaySec(final int pollDelaySec) { + this.pollDelaySec = pollDelaySec; } /** diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DDISimulatedDevice.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DDISimulatedDevice.java index 26e613dd9..677d77a37 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DDISimulatedDevice.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DDISimulatedDevice.java @@ -23,7 +23,6 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice { private static final Logger LOGGER = LoggerFactory.getLogger(DDISimulatedDevice.class); - private final int pollDelaySec; private final ControllerResource controllerResource; private final DeviceSimulatorUpdater deviceUpdater; @@ -45,11 +44,9 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice { */ public DDISimulatedDevice(final String id, final String tenant, final int pollDelaySec, final ControllerResource controllerResource, final DeviceSimulatorUpdater deviceUpdater) { - super(id, tenant, Protocol.DDI_HTTP); - this.pollDelaySec = pollDelaySec; + super(id, tenant, Protocol.DDI_HTTP, pollDelaySec); this.controllerResource = controllerResource; this.deviceUpdater = deviceUpdater; - setNextPollCounterSec(pollDelaySec); } @Override @@ -58,13 +55,10 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice { removed = true; } - public int getPollDelaySec() { - return pollDelaySec; - } - /** * Polls the base URL for the DDI API interface. */ + @Override public void poll() { if (!removed) { final String basePollJson = controllerResource.get(getTenant(), getId()); diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DMFSimulatedDevice.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DMFSimulatedDevice.java index 6b79a85b8..65227b55d 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DMFSimulatedDevice.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DMFSimulatedDevice.java @@ -8,10 +8,13 @@ */ package org.eclipse.hawkbit.simulator; +import org.eclipse.hawkbit.simulator.amqp.SpSenderService; + /** * A simulated device using the DMF API of the hawkBit update server. */ public class DMFSimulatedDevice extends AbstractSimulatedDevice { + private final SpSenderService spSenderService; /** * @param id @@ -19,8 +22,15 @@ public class DMFSimulatedDevice extends AbstractSimulatedDevice { * @param tenant * the tenant of the simulated device */ - public DMFSimulatedDevice(final String id, final String tenant) { - super(id, tenant, Protocol.DMF_AMQP); + public DMFSimulatedDevice(final String id, final String tenant, final SpSenderService spSenderService, + final int pollDelaySec) { + super(id, tenant, Protocol.DMF_AMQP, pollDelaySec); + this.spSenderService = spSenderService; + } + + @Override + public void poll() { + spSenderService.createOrUpdateThing(super.getTenant(), super.getId()); } } diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorRepository.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorRepository.java index 68db9df45..66ceacc8e 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorRepository.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/DeviceSimulatorRepository.java @@ -9,8 +9,8 @@ package org.eclipse.hawkbit.simulator; import java.util.Collection; -import java.util.LinkedHashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -25,7 +25,7 @@ import org.springframework.stereotype.Service; @Service public class DeviceSimulatorRepository { - private final Map devices = new LinkedHashMap<>(); + private final Map devices = new ConcurrentHashMap<>(); @Autowired private SimulatedDeviceFactory deviceFactory; diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/NextPollTimeController.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/NextPollTimeController.java index 956d6d36a..96b4a1e97 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/NextPollTimeController.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/NextPollTimeController.java @@ -8,12 +8,11 @@ */ package org.eclipse.hawkbit.simulator; -import java.util.List; +import java.util.Collection; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate; import org.slf4j.Logger; @@ -51,18 +50,17 @@ public class NextPollTimeController { private class NextPollUpdaterRunnable implements Runnable { @Override public void run() { - final List devices = repository.getAll().stream() - .filter(device -> device instanceof DDISimulatedDevice).collect(Collectors.toList()); + final Collection devices = repository.getAll(); devices.forEach(device -> { int nextCounter = device.getNextPollCounterSec() - 1; - if (nextCounter < 0 && device instanceof DDISimulatedDevice) { + if (nextCounter < 0) { try { - pollService.submit(() -> ((DDISimulatedDevice) device).poll()); + pollService.submit(() -> device.poll()); } catch (final IllegalStateException e) { LOGGER.trace("Device could not be polled", e); } - nextCounter = ((DDISimulatedDevice) device).getPollDelaySec(); + nextCounter = device.getPollDelaySec(); } device.setNextPollCounterSec(nextCounter); 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 f29aad001..35829c673 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 @@ -11,6 +11,7 @@ package org.eclipse.hawkbit.simulator; import java.net.URL; import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; +import org.eclipse.hawkbit.simulator.amqp.SpSenderService; import org.eclipse.hawkbit.simulator.http.ControllerResource; import org.eclipse.hawkbit.simulator.http.GatewayTokenInterceptor; import org.springframework.beans.factory.annotation.Autowired; @@ -28,6 +29,9 @@ public class SimulatedDeviceFactory { @Autowired private DeviceSimulatorUpdater deviceUpdater; + @Autowired + private SpSenderService spSenderService; + /** * Creating a simulated devices. * @@ -55,7 +59,7 @@ public class SimulatedDeviceFactory { * the protocol which should be used be the simulated device * @param pollDelaySec * the poll delay time in seconds which should be used for - * {@link DDISimulatedDevice}s + * {@link DDISimulatedDevice}s and {@link DMFSimulatedDevice} * @param baseEndpoint * the http base endpoint which should be used for * {@link DDISimulatedDevice}s @@ -68,7 +72,7 @@ public class SimulatedDeviceFactory { final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) { switch (protocol) { case DMF_AMQP: - return new DMFSimulatedDevice(id, tenant); + return new DMFSimulatedDevice(id, tenant, spSenderService, pollDelaySec); case DDI_HTTP: final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger()) .requestInterceptor(new GatewayTokenInterceptor(gatewayToken)).logLevel(Logger.Level.BASIC) 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 649d88477..3bd6b41f2 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 @@ -66,7 +66,7 @@ public class SimulationController { @RequestParam(value = "tenant", defaultValue = "DEFAULT") final String tenant, @RequestParam(value = "api", defaultValue = "dmf") final String api, @RequestParam(value = "endpoint", defaultValue = "http://localhost:8080") final String endpoint, - @RequestParam(value = "polldelay", defaultValue = "30") final int pollDelay, + @RequestParam(value = "polldelay", defaultValue = "1800") final int pollDelay, @RequestParam(value = "gatewaytoken", defaultValue = "") final String gatewayToken) throws MalformedURLException { diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationProperties.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationProperties.java index 354263934..fb98ff67e 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationProperties.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/SimulationProperties.java @@ -10,6 +10,7 @@ package org.eclipse.hawkbit.simulator; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; import org.hibernate.validator.constraints.NotEmpty; @@ -68,9 +69,9 @@ public class SimulationProperties { private String endpoint = "http://localhost:8080"; /** - * Poll time in case of DDI API based simulation. + * Poll time in {@link TimeUnit#SECONDS} for simulated devices. */ - private int pollDelay = 30; + private int pollDelay = (int) TimeUnit.MINUTES.toSeconds(30); /** * Optional gateway token for DDI API based simulation. 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 8ae2d87bd..5be5c7dcb 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 @@ -20,11 +20,13 @@ import org.springframework.amqp.core.FanoutExchange; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.QueueBuilder; import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; 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.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -73,6 +75,42 @@ public class AmqpConfiguration { return rabbitTemplate; } + @Configuration + protected static class RabbitConnectionFactoryCreator { + + /** + * {@link ConnectionFactory} with enabled publisher confirms and + * heartbeat. + * + * @param config + * with standard {@link RabbitProperties} + * @return {@link ConnectionFactory} + */ + @Bean + public ConnectionFactory rabbitConnectionFactory(final RabbitProperties config) { + final CachingConnectionFactory factory = new CachingConnectionFactory(); + factory.setRequestedHeartBeat(60); + factory.setPublisherConfirms(true); + + final String addresses = config.getAddresses(); + factory.setAddresses(addresses); + if (config.getHost() != null) { + factory.setHost(config.getHost()); + factory.setPort(config.getPort()); + } + if (config.getUsername() != null) { + factory.setUsername(config.getUsername()); + } + if (config.getPassword() != null) { + factory.setPassword(config.getPassword()); + } + if (config.getVirtualHost() != null) { + factory.setVirtualHost(config.getVirtualHost()); + } + return factory; + } + } + /** * Creates the receiver queue from update server for receiving message from * update server. diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/NextPollCounterUpdate.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/NextPollCounterUpdate.java index b9d7b9027..5e98ebb64 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/NextPollCounterUpdate.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/event/NextPollCounterUpdate.java @@ -8,7 +8,7 @@ */ package org.eclipse.hawkbit.simulator.event; -import java.util.List; +import java.util.Collection; import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; @@ -20,7 +20,7 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; */ public class NextPollCounterUpdate { - private final List devices; + private final Collection devices; /** * Creates poll timer update event. @@ -28,14 +28,14 @@ public class NextPollCounterUpdate { * @param devices * the devices which progress has been updated */ - public NextPollCounterUpdate(final List devices) { + public NextPollCounterUpdate(final Collection devices) { this.devices = devices; } /** * @return the devices of the event */ - public List getDevices() { + public Collection getDevices() { return devices; } 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 4834bece9..9405edd2b 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 @@ -8,7 +8,7 @@ */ package org.eclipse.hawkbit.simulator.ui; -import java.util.List; +import java.util.Collection; import java.util.Locale; import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; @@ -167,7 +167,7 @@ public class SimulatorView extends VerticalLayout implements View { @SuppressWarnings("unchecked") @Subscribe public void pollCounterUpdate(final NextPollCounterUpdate update) { - final List devices = update.getDevices(); + final Collection devices = update.getDevices(); this.getUI().access(() -> devices.forEach(device -> { final BeanItem item = beanContainer.getItem(device.getId()); if (item != null) { diff --git a/examples/hawkbit-device-simulator/src/main/resources/application.properties b/examples/hawkbit-device-simulator/src/main/resources/application.properties index fbe7261be..5d3f04be7 100644 --- a/examples/hawkbit-device-simulator/src/main/resources/application.properties +++ b/examples/hawkbit-device-simulator/src/main/resources/application.properties @@ -24,7 +24,6 @@ spring.rabbitmq.virtualHost=/ spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 spring.rabbitmq.dynamic=true -spring.rabbitmq.listener.prefetch=100 security.basic.enabled=false server.port=8083 diff --git a/examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml b/examples/hawkbit-device-simulator/src/main/resources/logback.xml similarity index 86% rename from examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml rename to examples/hawkbit-device-simulator/src/main/resources/logback.xml index f25a61cd1..5f3f1dbef 100644 --- a/examples/hawkbit-device-simulator/src/main/resources/logback-spring.xml +++ b/examples/hawkbit-device-simulator/src/main/resources/logback.xml @@ -20,11 +20,6 @@ - - - - - From cc1dc0951602b02a8f7f5d25bff13ecedd62c576 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Sun, 19 Jun 2016 20:43:12 +0200 Subject: [PATCH 16/46] Configurable prefetch and consumer pool. Signed-off-by: kaizimmerm --- hawkbit-dmf-amqp/pom.xml | 10 +++++++ .../hawkbit/amqp/AmqpConfiguration.java | 12 +++----- .../amqp/AmqpMessageHandlerService.java | 25 +++++++++-------- .../eclipse/hawkbit/amqp/AmqpProperties.java | 28 +++++++++++++++++++ .../amqp/AmqpMessageHandlerServiceTest.java | 17 +++++------ 5 files changed, 65 insertions(+), 27 deletions(-) diff --git a/hawkbit-dmf-amqp/pom.xml b/hawkbit-dmf-amqp/pom.xml index c2ed7c213..322dd5047 100644 --- a/hawkbit-dmf-amqp/pom.xml +++ b/hawkbit-dmf-amqp/pom.xml @@ -49,6 +49,11 @@ org.springframework.amqp spring-rabbit + + com.rabbitmq + amqp-client + 3.6.2 + org.springframework.security spring-security-web @@ -154,6 +159,11 @@ spring-context-support test + + org.scala-lang + scala-library + 2.10.4 + \ No newline at end of file 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 9435e8860..0e7e766e8 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 @@ -32,7 +32,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.task.TaskExecutor; import org.springframework.retry.backoff.ExponentialBackOffPolicy; import org.springframework.retry.support.RetryTemplate;; @@ -59,9 +58,6 @@ public class AmqpConfiguration { @Autowired private ConnectionFactory rabbitConnectionFactory; - @Autowired - private TaskExecutor taskExecutor; - @Configuration protected static class RabbitConnectionFactoryCreator { @@ -201,8 +197,8 @@ public class AmqpConfiguration { } /** - * Create the Binding {@link AmqpConfiguration#receiverQueueFromSp()} to - * {@link AmqpConfiguration#senderConnectorToSpExchange()}. + * Create the Binding {@link AmqpConfiguration#receiverQueue()} to + * {@link AmqpConfiguration#senderExchange()}. * * @return the binding and create the queue and exchange */ @@ -244,9 +240,9 @@ public class AmqpConfiguration { containerFactory.setDefaultRequeueRejected(true); containerFactory.setConnectionFactory(rabbitConnectionFactory); containerFactory.setMissingQueuesFatal(amqpProperties.isMissingQueuesFatal()); - containerFactory.setTaskExecutor(taskExecutor); - containerFactory.setConcurrentConsumers(3); + containerFactory.setConcurrentConsumers(amqpProperties.getInitialConcurrentConsumers()); containerFactory.setMaxConcurrentConsumers(amqpProperties.getMaxConcurrentConsumers()); + containerFactory.setPrefetchCount(amqpProperties.getPrefetchCount()); return containerFactory; } 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 107850fc1..caa11ab3d 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 @@ -37,6 +37,7 @@ import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; +import org.eclipse.hawkbit.repository.exception.TenantNotExistException; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.ActionStatus; @@ -47,6 +48,7 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.util.IpUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.amqp.AmqpRejectAndDontRequeueException; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.rabbit.annotation.RabbitListener; @@ -111,12 +113,6 @@ public class AmqpMessageHandlerService extends BaseAmqpService { super(defaultTemplate); } - @RabbitListener(queues = "${hawkbit.dmf.rabbitmq.receiverQueue}", containerFactory = "listenerContainerFactory") - private Message onMessage(final Message message, @Header(MessageHeaderKey.TYPE) final String type, - @Header(MessageHeaderKey.TENANT) final String tenant) { - return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost()); - } - /** * Method to handle all incoming amqp messages. * @@ -124,14 +120,17 @@ public class AmqpMessageHandlerService extends BaseAmqpService { * incoming message * @param type * the message type - * @param contentType - * the contentType of the message * @param tenant * the contentType of the message - * @param virtualHost - * the virtual host + * * @return a message if no message is send back to sender */ + @RabbitListener(queues = "${hawkbit.dmf.rabbitmq.receiverQueue}", containerFactory = "listenerContainerFactory") + public Message onMessage(final Message message, @Header(MessageHeaderKey.TYPE) final String type, + @Header(MessageHeaderKey.TENANT) final String tenant) { + return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost()); + } + public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) { checkContentTypeJson(message); final SecurityContext oldContext = SecurityContextHolder.getContext(); @@ -153,6 +152,10 @@ public class AmqpMessageHandlerService extends BaseAmqpService { default: logAndThrowMessageError(message, "No handle method was found for the given message type."); } + } catch (final IllegalArgumentException ex) { + throw new AmqpRejectAndDontRequeueException("Invalid message!", ex); + } catch (final TenantNotExistException teex) { + throw new AmqpRejectAndDontRequeueException(teex); } finally { SecurityContextHolder.setContext(oldContext); } @@ -421,7 +424,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService { } } - private void checkContentTypeJson(final Message message) { + private static void checkContentTypeJson(final Message message) { final MessageProperties messageProperties = message.getMessageProperties(); if (messageProperties.getContentType() != null && messageProperties.getContentType().contains("json")) { return; diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java index a20c59792..ace1fefa2 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java @@ -50,6 +50,34 @@ public class AmqpProperties { */ private int maxConcurrentConsumers = 10; + /** + * Tells the broker how many messages to send to each consumer in a single + * request. Often this can be set quite high to improve throughput. + */ + private int prefetchCount = 10; + + /** + * Initial number of consumers. Is scaled up if necessary up to + * {@link #maxConcurrentConsumers}. + */ + private int initialConcurrentConsumers = 3; + + public int getPrefetchCount() { + return prefetchCount; + } + + public void setPrefetchCount(final int prefetchCount) { + this.prefetchCount = prefetchCount; + } + + public int getInitialConcurrentConsumers() { + return initialConcurrentConsumers; + } + + public void setInitialConcurrentConsumers(final int initialConcurrentConsumers) { + this.initialConcurrentConsumers = initialConcurrentConsumers; + } + public int getMaxConcurrentConsumers() { return maxConcurrentConsumers; } 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 a0515a871..338feea62 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 @@ -59,6 +59,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.amqp.AmqpRejectAndDontRequeueException; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.rabbit.core.RabbitTemplate; @@ -170,7 +171,7 @@ public class AmqpMessageHandlerServiceTest { try { amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost"); fail("IllegalArgumentException was excepeted since no replyTo header was set"); - } catch (final IllegalArgumentException exception) { + } catch (final AmqpRejectAndDontRequeueException exception) { // test ok - exception was excepted } @@ -184,7 +185,7 @@ public class AmqpMessageHandlerServiceTest { try { amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost"); fail("IllegalArgumentException was excepeted since no thingID was set"); - } catch (final IllegalArgumentException exception) { + } catch (final AmqpRejectAndDontRequeueException exception) { // test ok - exception was excepted } } @@ -200,7 +201,7 @@ public class AmqpMessageHandlerServiceTest { try { amqpMessageHandlerService.onMessage(message, type, TENANT, "vHost"); fail("IllegalArgumentException was excepeted due to unknown message type"); - } catch (final IllegalArgumentException exception) { + } catch (final AmqpRejectAndDontRequeueException exception) { // test ok - exception was excepted } } @@ -213,21 +214,21 @@ public class AmqpMessageHandlerServiceTest { try { amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); fail("IllegalArgumentException was excepeted due to unknown message type"); - } catch (final IllegalArgumentException e) { + } catch (final AmqpRejectAndDontRequeueException e) { } try { messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic"); amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); fail("IllegalArgumentException was excepeted due to unknown topic"); - } catch (final IllegalArgumentException e) { + } catch (final AmqpRejectAndDontRequeueException e) { } messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name()); try { amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); fail("IllegalArgumentException was excepeted because there was no event topic"); - } catch (final IllegalArgumentException exception) { + } catch (final AmqpRejectAndDontRequeueException exception) { // test ok - exception was excepted } @@ -246,7 +247,7 @@ public class AmqpMessageHandlerServiceTest { try { amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); fail("IllegalArgumentException was excepeted since no action id was set"); - } catch (final IllegalArgumentException exception) { + } catch (final AmqpRejectAndDontRequeueException exception) { // test ok - exception was excepted } } @@ -263,7 +264,7 @@ public class AmqpMessageHandlerServiceTest { try { amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost"); fail("IllegalArgumentException was excepeted since no action id was set"); - } catch (final IllegalArgumentException exception) { + } catch (final AmqpRejectAndDontRequeueException exception) { // test ok - exception was excepted } From eac44899f2a357c20161afa66e86a8cb476917b3 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Sun, 19 Jun 2016 20:43:47 +0200 Subject: [PATCH 17/46] Completed configurable mgmt simulation scenario. Signed-off-by: kaizimmerm --- .../MgmtDistributionSetClientResource.java | 2 +- .../MgmtDistributionSetTagClientResource.java | 2 +- ...MgmtDistributionSetTypeClientResource.java | 2 +- .../MgmtDownloadArtifactClientResource.java | 2 +- .../resource/MgmtDownloadClientResource.java | 2 +- .../resource/MgmtRolloutClientResource.java | 2 +- .../MgmtSoftwareModuleClientResource.java | 3 ++- .../MgmtSoftwareModuleTypeClientResource.java | 2 +- .../resource/MgmtSystemClientResource.java | 2 +- .../MgmtSystemManagementClientResource.java | 2 +- .../resource/MgmtTargetClientResource.java | 2 +- .../resource/MgmtTargetTagClientResource.java | 2 +- .../builder/SoftwareModuleBuilder.java | 2 +- .../hawkbit/mgmt/client/Application.java | 12 ++++++++--- .../client/ClientConfigurationProperties.java | 9 -------- .../scenarios/ConfigurableScenario.java | 21 +++++++++---------- .../upload/FeignMultipartEncoder.java | 13 ++++++++---- .../src/main/resources/application.properties | 4 +++- .../{logback-spring.xml => logback.xml} | 12 +++-------- .../artifact/repository/ArtifactStore.java | 16 ++++---------- .../ArtifactStoreAutoConfiguration.java | 5 ----- 21 files changed, 52 insertions(+), 67 deletions(-) rename examples/hawkbit-example-mgmt-simulator/src/main/resources/{logback-spring.xml => logback.xml} (57%) diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetClientResource.java index 7bf696a8f..40eb13b55 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetClientResource.java @@ -15,7 +15,7 @@ import org.springframework.cloud.netflix.feign.FeignClient; /** * Client binding for the DistributionSet resource of the management API. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING) public interface MgmtDistributionSetClientResource extends MgmtDistributionSetRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTagClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTagClientResource.java index 783cc09fa..1070bbd9c 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTagClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTagClientResource.java @@ -15,6 +15,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; /** * Client binding for the DistributionSetTag resource of the management API. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING) public interface MgmtDistributionSetTagClientResource extends MgmtDistributionSetTagRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTypeClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTypeClientResource.java index 35f26781f..451c53942 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTypeClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDistributionSetTypeClientResource.java @@ -16,7 +16,7 @@ import org.springframework.cloud.netflix.feign.FeignClient; * Client binding for the DistributionSetType resource of the management API. * */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING) public interface MgmtDistributionSetTypeClientResource extends MgmtDistributionSetTypeRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadArtifactClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadArtifactClientResource.java index d25a609b2..5c93edce5 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadArtifactClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadArtifactClientResource.java @@ -16,7 +16,7 @@ import org.springframework.cloud.netflix.feign.FeignClient; * A feign-client interface declaration which allows to build a feign-client * stub. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING) public interface MgmtDownloadArtifactClientResource extends MgmtDownloadArtifactRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadClientResource.java index 9a1dcee61..330d3908f 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtDownloadClientResource.java @@ -15,6 +15,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; /** * */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.DOWNLOAD_ID_V1_REQUEST_MAPPING_BASE) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DOWNLOAD_ID_V1_REQUEST_MAPPING_BASE) public interface MgmtDownloadClientResource extends MgmtDownloadRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtRolloutClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtRolloutClientResource.java index d2643a938..acc00d6fe 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtRolloutClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtRolloutClientResource.java @@ -15,6 +15,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; /** * Client binding for the Rollout resource of the management API. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING) public interface MgmtRolloutClientResource extends MgmtRolloutRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleClientResource.java index 16ea188bd..7a2267e24 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleClientResource.java @@ -24,9 +24,10 @@ import feign.Param; /** * Client binding for the SoftwareModule resource of the management API. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING) public interface MgmtSoftwareModuleClientResource extends MgmtSoftwareModuleRestApi { + @Override @RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/artifacts") ResponseEntity uploadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId, @Param("file") final MultipartFile file, diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleTypeClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleTypeClientResource.java index 1e9462c47..603e82f10 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleTypeClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSoftwareModuleTypeClientResource.java @@ -15,6 +15,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; /** * Client binding for the SoftwareModuleType resource of the management API. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING) public interface MgmtSoftwareModuleTypeClientResource extends MgmtSoftwareModuleTypeRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemClientResource.java index 7d6967fed..e1bbd909c 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemClientResource.java @@ -16,6 +16,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; * Client binding for the {@link MgmtSystemRestApi}. * */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING) public interface MgmtSystemClientResource extends MgmtSystemRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemManagementClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemManagementClientResource.java index d1974b43f..802194fe8 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemManagementClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtSystemManagementClientResource.java @@ -16,7 +16,7 @@ import org.springframework.cloud.netflix.feign.FeignClient; * Client binding for the {@link MgmtSystemManagementRestApi}. * */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.SYSTEM_ADMIN_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SYSTEM_ADMIN_MAPPING) public interface MgmtSystemManagementClientResource extends MgmtSystemManagementRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetClientResource.java index 872c4251a..c0a0193af 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetClientResource.java @@ -15,6 +15,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; /** * Client binding for the Target resource of the management API. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.TARGET_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.TARGET_V1_REQUEST_MAPPING) public interface MgmtTargetClientResource extends MgmtTargetRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetTagClientResource.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetTagClientResource.java index 7b0c213af..3f9264337 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetTagClientResource.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/MgmtTargetTagClientResource.java @@ -15,6 +15,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; /** * Client binding for the TargetTag resource of the management API. */ -@FeignClient(url = "${hawkbit.url:localhost:8080}/" + MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING) +@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING) public interface MgmtTargetTagClientResource extends MgmtTargetTagRestApi { } diff --git a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java index 1d633e440..db7941bfc 100644 --- a/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java +++ b/examples/hawkbit-example-mgmt-feign-client/src/main/java/org/eclipse/hawkbit/mgmt/client/resource/builder/SoftwareModuleBuilder.java @@ -90,7 +90,7 @@ public class SoftwareModuleBuilder { * @return a single entry list of {@link MgmtSoftwareModuleRequestBodyPost} */ public List build() { - return Lists.newArrayList(doBuild(name)); + return Lists.newArrayList(doBuild("")); } /** diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java index e89f3211b..8ebd8830a 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java @@ -35,9 +35,10 @@ import feign.Feign; import feign.Logger; import feign.auth.BasicAuthRequestInterceptor; import feign.jackson.JacksonDecoder; +import feign.slf4j.Slf4jLogger; @SpringBootApplication -@EnableFeignClients +@EnableFeignClients("org.eclipse.hawkbit.mgmt.client.resource") @EnableConfigurationProperties(ClientConfigurationProperties.class) @Configuration @AutoConfigureAfter(FeignClientConfiguration.class) @@ -83,6 +84,11 @@ public class Application implements CommandLineRunner { return new CreateStartedRolloutExample(); } + @Bean + public Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } + @Bean public MgmtSoftwareModuleClientResource uploadSoftwareModule() { final ObjectMapper mapper = new ObjectMapper() @@ -92,13 +98,13 @@ public class Application implements CommandLineRunner { return Feign.builder().contract(new IgnoreMultipleConsumersProducersSpringMvcContract()) .requestInterceptor( new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword())) - .logger(new Logger.ErrorLogger()).encoder(new FeignMultipartEncoder()) + .logger(new Slf4jLogger()).encoder(new FeignMultipartEncoder()) .decoder(new ResponseEntityDecoder(new JacksonDecoder(mapper))) .target(MgmtSoftwareModuleClientResource.class, configuration.getUrl() + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING); } - private boolean containsArg(final String containsArg, final String... args) { + private static boolean containsArg(final String containsArg, final String... args) { for (final String arg : args) { if (arg.equalsIgnoreCase(containsArg)) { return true; diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java index 8a5c61575..83a0844d4 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java @@ -44,7 +44,6 @@ public class ClientConfigurationProperties { * */ public static class Scenario { - private String tenant = "DEFAULT"; private boolean cleanRepository; private int targets = 100; private int distributionSets = 10; @@ -96,14 +95,6 @@ public class ClientConfigurationProperties { this.targetAddress = targetAddress; } - public String getTenant() { - return tenant; - } - - public void setTenant(final String tenant) { - this.tenant = tenant; - } - public int getArtifactsPerSM() { return artifactsPerSM; } diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java index 84b3da6ee..240f94568 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java @@ -1,5 +1,5 @@ /** -x * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * 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 @@ -159,10 +159,9 @@ public class ConfigurableScenario { LOGGER.info("Creating {} distribution sets", scenario.getDistributionSets()); final byte[] artifact = generateArtifact(scenario); - distributionSetResource - .createDistributionSets(new DistributionSetBuilder().name(scenario.getDsName()).type("os_app") - .version("1.0.").buildAsList(scenario.getDistributionSets())) - .getBody().parallelStream().forEach(dsSet -> { + distributionSetResource.createDistributionSets(new DistributionSetBuilder().name(scenario.getDsName()) + .type("os_app").version("1.0.").buildAsList(scenario.getDistributionSets())).getBody() + .forEach(dsSet -> { final List modules = addModules(scenario, dsSet, artifact); final SoftwareModuleAssigmentBuilder assign = new SoftwareModuleAssigmentBuilder(); @@ -175,13 +174,13 @@ public class ConfigurableScenario { private List addModules(final Scenario scenario, final MgmtDistributionSet dsSet, final byte[] artifact) { - final List modules = softwareModuleResource.createSoftwareModules( - new SoftwareModuleBuilder().name(scenario.getSmFwName()).version(dsSet.getVersion()).type("os").build()) + final List modules = softwareModuleResource + .createSoftwareModules(new SoftwareModuleBuilder().name(scenario.getSmFwName() + "-os") + .version(dsSet.getVersion()).type("os").build()) .getBody(); - modules.addAll(softwareModuleResource - .createSoftwareModules( - new SoftwareModuleBuilder().name(scenario.getSmSwName()).version(dsSet.getVersion() + ".") - .type("application").buildAsList(scenario.getAppModulesPerDistributionSet())) + modules.addAll(softwareModuleResource.createSoftwareModules( + new SoftwareModuleBuilder().name(scenario.getSmSwName() + "-app").version(dsSet.getVersion() + ".") + .type("application").buildAsList(scenario.getAppModulesPerDistributionSet())) .getBody()); for (int x = 0; x < scenario.getArtifactsPerSM(); x++) { diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java index fdf5462da..00424c5e5 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java @@ -1,5 +1,10 @@ /** - * Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved. + * 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.mgmt.client.scenarios.upload; @@ -100,16 +105,16 @@ public class FeignMultipartEncoder implements Encoder { } } - private boolean isMultipartFile(final Object object) { + private static boolean isMultipartFile(final Object object) { return object instanceof MultipartFile; } - private class HttpOutputMessageImpl implements HttpOutputMessage { + private static final class HttpOutputMessageImpl implements HttpOutputMessage { private final OutputStream body; private final HttpHeaders headers; - public HttpOutputMessageImpl(final OutputStream body, final HttpHeaders headers) { + private HttpOutputMessageImpl(final OutputStream body, final HttpHeaders headers) { this.body = body; this.headers = headers; } diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties index e19b83e19..ac3f240a3 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties +++ b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties @@ -13,8 +13,10 @@ hawkbit.password=admin spring.main.show-banner=false +hawkbit.scenarios.[0].cleanRepository=true hawkbit.scenarios.[0].targets=0 hawkbit.scenarios.[0].ds-name=gettingstarted-example hawkbit.scenarios.[0].distribution-sets=3 hawkbit.scenarios.[0].sm-fw-name=gettingstarted-example -hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example \ No newline at end of file +hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example +hawkbit.scenarios.[0].runRollouts=false \ No newline at end of file diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml b/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback.xml similarity index 57% rename from examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml rename to examples/hawkbit-example-mgmt-simulator/src/main/resources/logback.xml index 0174611e6..768f30687 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback-spring.xml +++ b/examples/hawkbit-example-mgmt-simulator/src/main/resources/logback.xml @@ -10,17 +10,11 @@ --> - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - + - + - + diff --git a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java index aa9ff3409..eabd2b329 100644 --- a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java +++ b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStore.java @@ -87,9 +87,7 @@ public class ArtifactStore implements ArtifactRepository { /** * Retrieves a {@link GridFSDBFile} from the store by it's MD5 hash. - * - * @param tenant - * the tenant to retrieve the artifacts from, ignore case. + * * @param md5Hash * the md5-hash of the file to lookup. * @return The gridfs file object or {@code null} if no file exists. @@ -100,9 +98,7 @@ public class ArtifactStore implements ArtifactRepository { /** * Retrieves a {@link GridFSDBFile} from the store by it's object id. - * - * @param tenant - * the tenant to retrieve the artifacts from, ignore case. + * * @param id * the id of the file to lookup. * @return The gridfs file object or {@code null} if no file exists. @@ -231,15 +227,13 @@ public class ArtifactStore implements ArtifactRepository { * @return a paged list of artifacts mapped from the given dbFiles */ private List map(final List dbFiles) { - return dbFiles.stream().map(dbFile -> map(dbFile)).collect(Collectors.toList()); + return dbFiles.stream().map(this::map).collect(Collectors.toList()); } /** * Retrieves a list of {@link GridFSDBFile} from the store by all SHA1 * hashes. - * - * @param tenant - * the tenant to retrieve the artifacts from, ignore case. + * * @param sha1Hashes * the sha1-hashes of the files to lookup. * @return list of artifacts @@ -252,8 +246,6 @@ public class ArtifactStore implements ArtifactRepository { /** * Retrieves a list of {@link GridFSDBFile} from the store by all ids. * - * @param tenant - * the tenant to retrieve the artifacts from, ignore case. * @param ids * the ids of the files to lookup. * @return list of artfiacts diff --git a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreAutoConfiguration.java b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreAutoConfiguration.java index 43bcddaf0..8a1cb89a9 100644 --- a/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreAutoConfiguration.java +++ b/hawkbit-artifact-repository-mongo/src/main/java/org/eclipse/hawkbit/artifact/repository/ArtifactStoreAutoConfiguration.java @@ -10,18 +10,13 @@ package org.eclipse.hawkbit.artifact.repository; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; /** * Auto configuration for the {@link ArtifactStore}. - * - * - * */ @Configuration -@ComponentScan @ConditionalOnMissingBean(value = ArtifactRepository.class) @Import(value = MongoConfiguration.class) public class ArtifactStoreAutoConfiguration { From fb59dca1687b4d54b1313ddebff63bb4d8de35f9 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Mon, 20 Jun 2016 08:46:50 +0200 Subject: [PATCH 18/46] Added configurable late feedback functionality, i.e. action feedback still allowed even for closed action. Signed-off-by: kaizimmerm --- .../repository/RepositoryProperties.java | 29 ++++++ .../hawkbit-repository-jpa/pom.xml | 8 ++ .../RepositoryApplicationConfiguration.java | 5 +- .../jpa/JpaControllerManagement.java | 31 +++++- .../jpa/ControllerManagementTest.java | 95 ++++++++++++++++++- 5 files changed, 161 insertions(+), 7 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java new file mode 100644 index 000000000..982003812 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java @@ -0,0 +1,29 @@ +package org.eclipse.hawkbit.repository; + +import org.eclipse.hawkbit.repository.model.ActionStatus; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration properties for the repository. + * + */ +@ConfigurationProperties("hawkbit.server.repository") +public class RepositoryProperties { + + /** + * Set to true if the repository has to reject + * {@link ActionStatus} entries for actions that are closed. Note: if this + * is enforced you have to make sure that the feedback channel from the + * devices i in order. + */ + private boolean rejectActionStatusForClosedAction = false; + + public boolean isRejectActionStatusForClosedAction() { + return rejectActionStatusForClosedAction; + } + + public void setRejectActionStatusForClosedAction(final boolean rejectActionStatusForClosedAction) { + this.rejectActionStatusForClosedAction = rejectActionStatusForClosedAction; + } + +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/pom.xml b/hawkbit-repository/hawkbit-repository-jpa/pom.xml index bd56e9ca5..b1d60ec08 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/pom.xml +++ b/hawkbit-repository/hawkbit-repository-jpa/pom.xml @@ -136,6 +136,14 @@ fest-assert test + + org.springframework.boot + spring-boot-starter-hornetq + + + org.springframework.boot + spring-boot-starter-hornetq + 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 50207037a..0f1d98166 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 @@ -11,6 +11,7 @@ package org.eclipse.hawkbit; import java.util.HashMap; import java.util.Map; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.jpa.aspects.ExceptionMappingAspectHandler; @@ -27,6 +28,7 @@ import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -40,7 +42,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; /** - * General configuration for the SP Repository. + * General configuration for hawlBit's Repository. * */ @EnableJpaRepositories(basePackages = { "org.eclipse.hawkbit.repository.jpa" }) @@ -50,6 +52,7 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess @Configuration @ComponentScan @EnableAutoConfiguration +@EnableConfigurationProperties(RepositoryProperties.class) public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { /** * @return the {@link SystemSecurityContext} singleton bean which make it diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index 77b71e661..b8922c151 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -21,6 +21,7 @@ import javax.validation.constraints.NotNull; import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; @@ -94,6 +95,9 @@ public class JpaControllerManagement implements ControllerManagement { @Autowired private HawkbitSecurityProperties securityProperties; + @Autowired + private RepositoryProperties repositoryProperties; + @Autowired private TenantConfigurationRepository tenantConfigurationRepository; @@ -251,7 +255,13 @@ public class JpaControllerManagement implements ControllerManagement { public Action addUpdateActionStatus(@NotNull final ActionStatus actionStatus) { final JpaAction action = (JpaAction) actionStatus.getAction(); - if (!action.isActive()) { + // TODO: test + // if action is already closed we accept further status updates on if + // permitted so by configuration. This is especially use full if the + // action status feedback channel order from the device cannot be + // guaranteed. However, if an action is closed we do not accept further + // close messages. + if (actionIsNotActiveButIntermediateFeedbackStillAllowed(actionStatus, action)) { LOG.debug("Update of actionStatus {} for action {} not possible since action not active anymore.", actionStatus.getId(), action.getId()); return action; @@ -259,6 +269,12 @@ public class JpaControllerManagement implements ControllerManagement { return handleAddUpdateActionStatus((JpaActionStatus) actionStatus, action); } + private boolean actionIsNotActiveButIntermediateFeedbackStillAllowed(final ActionStatus actionStatus, + final JpaAction action) { + return !action.isActive() && (repositoryProperties.isRejectActionStatusForClosedAction() + || (Status.ERROR.equals(actionStatus.getStatus()) || Status.FINISHED.equals(actionStatus.getStatus()))); + } + /** * Sets {@link TargetUpdateStatus} based on given {@link ActionStatus}. * @@ -286,8 +302,7 @@ public class JpaControllerManagement implements ControllerManagement { case CANCELED: case WARNING: case RUNNING: - DeploymentHelper.updateTargetInfo(mergedTarget, TargetUpdateStatus.PENDING, false, targetInfoRepository, - entityManager); + handleIntermediateFeedback(mergedAction, mergedTarget); break; default: break; @@ -300,6 +315,16 @@ public class JpaControllerManagement implements ControllerManagement { return actionRepository.save(mergedAction); } + private void handleIntermediateFeedback(final JpaAction mergedAction, final JpaTarget mergedTarget) { + // we change the target state only if the action is still running + // otherwise this is considered as late feedback that does not have + // an impact on the state anymore. + if (mergedAction.isActive()) { + DeploymentHelper.updateTargetInfo(mergedTarget, TargetUpdateStatus.PENDING, false, targetInfoRepository, + entityManager); + } + } + private void handleErrorOnAction(final JpaAction mergedAction, final JpaTarget mergedTarget) { mergedAction.setActive(false); mergedAction.setStatus(Status.ERROR); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java index f33c5c170..77adfa45b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java @@ -17,6 +17,7 @@ import java.util.List; import javax.validation.ConstraintViolationException; import org.apache.commons.lang3.RandomStringUtils; +import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.model.Action; @@ -26,6 +27,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Features; @@ -34,6 +36,8 @@ import ru.yandex.qatools.allure.annotations.Stories; @Features("Component Tests - Repository") @Stories("Controller Management") public class ControllerManagementTest extends AbstractJpaIntegrationTest { + @Autowired + private RepositoryProperties repositoryProperties; @Test @Description("Controller adds a new action status.") @@ -94,7 +98,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { @Test @Description("Controller trys to finish an update process after it has been finished by an error action status.") - public void tryToFinishUpdateProcessMoreThenOnce() { + public void tryToFinishUpdateProcessMoreThanOnce() { // mock final Target target = new JpaTarget("Rabbit"); @@ -120,16 +124,101 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest { assertThat(targetManagement.findTargetByControllerID("Rabbit").getTargetInfo().getUpdateStatus()) .isEqualTo(TargetUpdateStatus.ERROR); + // try with disabled late feedback + repositoryProperties.setRejectActionStatusForClosedAction(true); final ActionStatus actionStatusMessage3 = new JpaActionStatus(savedAction, Action.Status.FINISHED, System.currentTimeMillis()); actionStatusMessage3.addMessage("finish"); - controllerManagament.addUpdateActionStatus(actionStatusMessage3); + savedAction = controllerManagament.addUpdateActionStatus(actionStatusMessage3); - targetManagement.findTargetByControllerID("Rabbit").getTargetInfo().getUpdateStatus(); + // test + assertThat(targetManagement.findTargetByControllerID("Rabbit").getTargetInfo().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.ERROR); + + // try with enabled late feedback + repositoryProperties.setRejectActionStatusForClosedAction(false); + final ActionStatus actionStatusMessage4 = new JpaActionStatus(savedAction, Action.Status.FINISHED, + System.currentTimeMillis()); + actionStatusMessage4.addMessage("finish"); + controllerManagament.addUpdateActionStatus(actionStatusMessage3); // test assertThat(targetManagement.findTargetByControllerID("Rabbit").getTargetInfo().getUpdateStatus()) .isEqualTo(TargetUpdateStatus.ERROR); } + + @Test + @Description("Controller trys to send an update feedback after it has been finished which is reject as the repository is " + + "configured to reject that.") + public void sendUpdatesForFinishUpdateProcessDropedIfDisabled() { + repositoryProperties.setRejectActionStatusForClosedAction(true); + + final Action action = prepareFinishedUpdate("Rabbit"); + + final ActionStatus actionStatusMessage1 = new JpaActionStatus(action, Action.Status.RUNNING, + System.currentTimeMillis()); + actionStatusMessage1.addMessage("got some additional feedback"); + controllerManagament.addUpdateActionStatus(actionStatusMessage1); + + // nothing changed as "feedback after close" is disabled + assertThat(targetManagement.findTargetByControllerID("Rabbit").getTargetInfo().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.IN_SYNC); + assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3); + assertThat(deploymentManagement.findActionStatusByAction(pageReq, action).getNumberOfElements()).isEqualTo(3); + } + + @Test + @Description("Controller trys to send an update feedback after it has been finished which is actepted as the repository is " + + "configured to accept them.") + public void sendUpdatesForFinishUpdateProcessAcceptedIfEnabled() { + repositoryProperties.setRejectActionStatusForClosedAction(false); + + Action action = prepareFinishedUpdate("Rabbit"); + + final ActionStatus actionStatusMessage1 = new JpaActionStatus(action, Action.Status.RUNNING, + System.currentTimeMillis()); + actionStatusMessage1.addMessage("got some additional feedback"); + action = controllerManagament.addUpdateActionStatus(actionStatusMessage1); + + // nothing changed as "feedback after close" is disabled + assertThat(targetManagement.findTargetByControllerID("Rabbit").getTargetInfo().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.IN_SYNC); + assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(4); + assertThat(deploymentManagement.findActionStatusByAction(pageReq, action).getNumberOfElements()).isEqualTo(4); + } + + private Action prepareFinishedUpdate(final String controllerId) { + // mock + final Target target = new JpaTarget(controllerId); + final DistributionSet ds = testdataFactory.createDistributionSet(""); + Target savedTarget = targetManagement.createTarget(target); + final List toAssign = new ArrayList<>(); + toAssign.add(savedTarget); + savedTarget = deploymentManagement.assignDistributionSet(ds, toAssign).getAssignedEntity().iterator().next(); + Action savedAction = deploymentManagement.findActiveActionsByTarget(savedTarget).get(0); + + // test and verify + final ActionStatus actionStatusMessage = new JpaActionStatus(savedAction, Action.Status.RUNNING, + System.currentTimeMillis()); + actionStatusMessage.addMessage("running"); + savedAction = controllerManagament.addUpdateActionStatus(actionStatusMessage); + assertThat(targetManagement.findTargetByControllerID(controllerId).getTargetInfo().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.PENDING); + + final ActionStatus actionStatusMessage2 = new JpaActionStatus(savedAction, Action.Status.FINISHED, + System.currentTimeMillis()); + actionStatusMessage2.addMessage("finish"); + savedAction = controllerManagament.addUpdateActionStatus(actionStatusMessage2); + + // test + assertThat(targetManagement.findTargetByControllerID(controllerId).getTargetInfo().getUpdateStatus()) + .isEqualTo(TargetUpdateStatus.IN_SYNC); + + assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3); + assertThat(deploymentManagement.findActionStatusByAction(pageReq, savedAction).getNumberOfElements()) + .isEqualTo(3); + + return savedAction; + } } From 2044695aeb75464455219d39c923c2a76956a501 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Mon, 20 Jun 2016 08:56:40 +0200 Subject: [PATCH 19/46] Fixed license header. Signed-off-by: kaizimmerm --- .../eclipse/hawkbit/repository/RepositoryProperties.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java index 982003812..c60089fb3 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RepositoryProperties.java @@ -1,3 +1,11 @@ +/** + * 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 org.eclipse.hawkbit.repository.model.ActionStatus; From dbb2e00ed86b54cf6be3ff3b82911d95abf89275 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Mon, 20 Jun 2016 10:16:15 +0200 Subject: [PATCH 20/46] re-order tenant lazy initialization filter after authentication chain Signed-off-by: Michael Hirsch --- .../autoconfigure/security/SecurityManagedConfiguration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 fc7a0a1e4..0b68246ff 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 @@ -83,6 +83,7 @@ import org.springframework.security.web.header.writers.frameoptions.StaticAllowF import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter; import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode; import org.springframework.security.web.session.HttpSessionEventPublisher; +import org.springframework.security.web.session.SessionManagementFilter; import org.vaadin.spring.security.VaadinSecurityContext; import org.vaadin.spring.security.annotation.EnableVaadinSecurity; import org.vaadin.spring.security.web.VaadinDefaultRedirectStrategy; @@ -333,7 +334,7 @@ public class SecurityManagedConfiguration { }, RequestHeaderAuthenticationFilter.class) .addFilterAfter( new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement), - RequestHeaderAuthenticationFilter.class) + SessionManagementFilter.class) .authorizeRequests().anyRequest().authenticated() .antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/admin/**") .hasAnyAuthority(SpPermission.SYSTEM_ADMIN) From deb1dde32646a7a5266e658642f6ccff57d4ec7e Mon Sep 17 00:00:00 2001 From: SirWayne Date: Tue, 21 Jun 2016 09:45:28 +0200 Subject: [PATCH 21/46] Add select all for mac osx Signed-off-by: SirWayne --- .../smtable/SoftwareModuleTableLayout.java | 5 -- .../ui/common/table/AbstractTableLayout.java | 85 +++++++++++-------- .../dstable/DistributionSetTableLayout.java | 5 -- .../smtable/SwModuleTableLayout.java | 6 -- .../dstable/DistributionTableLayout.java | 5 -- 5 files changed, 51 insertions(+), 55 deletions(-) diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java index 2672c4546..421fbc89c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/smtable/SoftwareModuleTableLayout.java @@ -42,9 +42,4 @@ public class SoftwareModuleTableLayout extends AbstractTableLayout { super.init(smTableHeader, smTable, softwareModuleDetails); } - @Override - protected void publishEvent() { - // nothing to publish - } - } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java index 98874626d..905c5917c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java @@ -9,11 +9,12 @@ package org.eclipse.hawkbit.ui.common.table; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractTableDetailsLayout; -import org.springframework.beans.factory.annotation.Autowired; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.ShortcutAction; +import com.vaadin.server.Page; +import com.vaadin.server.WebBrowser; import com.vaadin.ui.Alignment; import com.vaadin.ui.Panel; import com.vaadin.ui.VerticalLayout; @@ -24,22 +25,16 @@ import com.vaadin.ui.themes.ValoTheme; */ public abstract class AbstractTableLayout extends VerticalLayout { - private static final long serialVersionUID = 8611248179949245460L; - - /** - * action for the shortcut key ctrl + 'A'. - */ - protected static final ShortcutAction ACTION_CTRL_A = new ShortcutAction("Select All", ShortcutAction.KeyCode.A, - new int[] { ShortcutAction.ModifierKey.CTRL }); + private static final long serialVersionUID = 1L; private AbstractTableHeader tableHeader; - private AbstractTable table; + private AbstractTable table; - private AbstractTableDetailsLayout detailsLayout; + private AbstractTableDetailsLayout detailsLayout; - protected void init(final AbstractTableHeader tableHeader, final AbstractTable table, - final AbstractTableDetailsLayout detailsLayout) { + protected void init(final AbstractTableHeader tableHeader, final AbstractTable table, + final AbstractTableDetailsLayout detailsLayout) { this.tableHeader = tableHeader; this.table = table; this.detailsLayout = detailsLayout; @@ -63,24 +58,24 @@ public abstract class AbstractTableLayout extends VerticalLayout { if (isShortCutKeysRequired()) { final Panel tablePanel = new Panel(); tablePanel.setStyleName("table-panel"); - tablePanel.setHeight(100.0f, Unit.PERCENTAGE); + tablePanel.setHeight(100.0F, Unit.PERCENTAGE); tablePanel.setContent(table); tablePanel.addActionHandler(getShortCutKeysHandler()); tablePanel.addStyleName(ValoTheme.PANEL_BORDERLESS); tableHeaderLayout.addComponent(tablePanel); tableHeaderLayout.setComponentAlignment(tablePanel, Alignment.TOP_CENTER); - tableHeaderLayout.setExpandRatio(tablePanel, 1.0f); + tableHeaderLayout.setExpandRatio(tablePanel, 1.0F); } else { tableHeaderLayout.addComponent(table); tableHeaderLayout.setComponentAlignment(table, Alignment.TOP_CENTER); - tableHeaderLayout.setExpandRatio(table, 1.0f); + tableHeaderLayout.setExpandRatio(table, 1.0F); } addComponent(tableHeaderLayout); addComponent(detailsLayout); setComponentAlignment(tableHeaderLayout, Alignment.TOP_CENTER); setComponentAlignment(detailsLayout, Alignment.TOP_CENTER); - setExpandRatio(tableHeaderLayout, 1.0f); + setExpandRatio(tableHeaderLayout, 1.0F); } /** @@ -99,29 +94,51 @@ public abstract class AbstractTableLayout extends VerticalLayout { * Default is null. */ protected Handler getShortCutKeysHandler() { - return new Handler() { - - private static final long serialVersionUID = 1L; - - @Override - public void handleAction(final Action action, final Object sender, final Object target) { - if (ACTION_CTRL_A.equals(action)) { - table.selectAll(); - publishEvent(); - } - } - - @Override - public Action[] getActions(final Object target, final Object sender) { - return new Action[] { ACTION_CTRL_A }; - } - }; + return new TableShortCutHandler(); } - protected abstract void publishEvent(); + protected void publishEvent() { + // can be override by subclasses + } public void setShowFilterButtonVisible(final boolean visible) { tableHeader.setFilterButtonsIconVisible(visible); } + private class TableShortCutHandler implements Handler { + + private static final String SELECT_ALL_TEXT = "Select All"; + private final ShortcutAction selectAllAction = new ShortcutAction(SELECT_ALL_TEXT, ShortcutAction.KeyCode.A, + new int[] { ShortcutAction.ModifierKey.CTRL }); + + private final ShortcutAction selectAllMacAction = new ShortcutAction(SELECT_ALL_TEXT, ShortcutAction.KeyCode.A, + new int[] { ShortcutAction.ModifierKey.META }); + + private static final long serialVersionUID = 1L; + + @Override + public void handleAction(final Action action, final Object sender, final Object target) { + if (!isSelecAllAction(action)) { + return; + } + table.selectAll(); + publishEvent(); + } + + private boolean isSelecAllAction(final Action action) { + return selectAllAction.equals(action) || selectAllMacAction.equals(action); + } + + @Override + public Action[] getActions(final Object target, final Object sender) { + + final WebBrowser webBrowser = Page.getCurrent().getWebBrowser(); + if (webBrowser.isMacOSX()) { + return new Action[] { selectAllMacAction }; + } + + return new Action[] { selectAllAction }; + } + } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java index 66c8aff0e..e15189f6a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/dstable/DistributionSetTableLayout.java @@ -46,9 +46,4 @@ public class DistributionSetTableLayout extends AbstractTableLayout { super.init(dsTableHeader, dsTable, distributionDetails); } - @Override - protected void publishEvent() { - // nothing to publish - } - } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java index e0d4b8ac6..9d298207a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/smtable/SwModuleTableLayout.java @@ -41,10 +41,4 @@ public class SwModuleTableLayout extends AbstractTableLayout { void init() { super.init(swModuleTableHeader, swModuleTable, swModuleDetails); } - - @Override - protected void publishEvent() { - // nothing to publish - } - } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java index fefbca972..0d9a782a1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/dstable/DistributionTableLayout.java @@ -42,9 +42,4 @@ public class DistributionTableLayout extends AbstractTableLayout { super.init(dsTableHeader, dsTable, distributionDetails); } - @Override - protected void publishEvent() { - // nothing to publish - } - } From 437b77a1a8002e5204ceac8a992ea23eab70d758 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Tue, 21 Jun 2016 11:00:58 +0200 Subject: [PATCH 22/46] Completed configurable demo generator. Signed-off-by: kaizimmerm --- .../hawkbit/mgmt/client/Application.java | 13 +++++-- .../scenarios/ConfigurableScenario.java | 34 +++++++++++-------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java index 8ebd8830a..ac65455b5 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/Application.java @@ -10,12 +10,16 @@ package org.eclipse.hawkbit.mgmt.client; import org.eclipse.hawkbit.feign.core.client.FeignClientConfiguration; import org.eclipse.hawkbit.feign.core.client.IgnoreMultipleConsumersProducersSpringMvcContract; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtRolloutClientResource; import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource; +import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource; import org.eclipse.hawkbit.mgmt.client.scenarios.ConfigurableScenario; import org.eclipse.hawkbit.mgmt.client.scenarios.CreateStartedRolloutExample; import org.eclipse.hawkbit.mgmt.client.scenarios.upload.FeignMultipartEncoder; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -75,8 +79,13 @@ public class Application implements CommandLineRunner { } @Bean - public ConfigurableScenario configurableScenario() { - return new ConfigurableScenario(); + public ConfigurableScenario configurableScenario(final MgmtDistributionSetClientResource distributionSetResource, + @Qualifier("mgmtSoftwareModuleClientResource") final MgmtSoftwareModuleClientResource softwareModuleResource, + @Qualifier("uploadSoftwareModule") final MgmtSoftwareModuleClientResource uploadSoftwareModule, + final MgmtTargetClientResource targetResource, final MgmtRolloutClientResource rolloutResource, + final ClientConfigurationProperties clientConfigurationProperties) { + return new ConfigurableScenario(distributionSetResource, softwareModuleResource, uploadSoftwareModule, + targetResource, rolloutResource, clientConfigurationProperties); } @Bean diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java index 240f94568..33afefa26 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java @@ -31,7 +31,6 @@ import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; /** @@ -43,25 +42,30 @@ public class ConfigurableScenario { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurableScenario.class); - @Autowired - private MgmtDistributionSetClientResource distributionSetResource; + private final MgmtDistributionSetClientResource distributionSetResource; - @Autowired - @Qualifier("mgmtSoftwareModuleClientResource") - private MgmtSoftwareModuleClientResource softwareModuleResource; + private final MgmtSoftwareModuleClientResource softwareModuleResource; - @Autowired - @Qualifier("uploadSoftwareModule") - private MgmtSoftwareModuleClientResource uploadSoftwareModule; + private final MgmtSoftwareModuleClientResource uploadSoftwareModule; - @Autowired - private MgmtTargetClientResource targetResource; + private final MgmtTargetClientResource targetResource; - @Autowired - private MgmtRolloutClientResource rolloutResource; + private final MgmtRolloutClientResource rolloutResource; - @Autowired - private ClientConfigurationProperties clientConfigurationProperties; + private final ClientConfigurationProperties clientConfigurationProperties; + + public ConfigurableScenario(final MgmtDistributionSetClientResource distributionSetResource, + @Qualifier("mgmtSoftwareModuleClientResource") final MgmtSoftwareModuleClientResource softwareModuleResource, + @Qualifier("uploadSoftwareModule") final MgmtSoftwareModuleClientResource uploadSoftwareModule, + final MgmtTargetClientResource targetResource, final MgmtRolloutClientResource rolloutResource, + final ClientConfigurationProperties clientConfigurationProperties) { + this.distributionSetResource = distributionSetResource; + this.softwareModuleResource = softwareModuleResource; + this.uploadSoftwareModule = uploadSoftwareModule; + this.targetResource = targetResource; + this.rolloutResource = rolloutResource; + this.clientConfigurationProperties = clientConfigurationProperties; + } /** * Run the default getting started scenario. From dfa547d382a7713055891b1cb58d3f5249d1c323 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 21 Jun 2016 11:14:22 +0200 Subject: [PATCH 23/46] update jacoco version Signed-off-by: Michael Hirsch --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f50afa0ab..de7a9dd6d 100644 --- a/pom.xml +++ b/pom.xml @@ -127,7 +127,7 @@ https://projects.eclipse.org/projects/iot.hawkbit https://circleci.com/gh/eclipse/hawkbit - 0.7.6.201602180812 + 0.7.7.201606060606 1.4 From b7ea17498367d6727cd7149534ecca6f5156662e Mon Sep 17 00:00:00 2001 From: SirWayne Date: Tue, 21 Jun 2016 13:42:26 +0200 Subject: [PATCH 24/46] Add a shortcut modifier util class to handle cross platform functionality. Signed-off-by: SirWayne --- .../ui/common/table/AbstractTableLayout.java | 20 ++------- .../ui/utils/ShortCutModifierUtils.java | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/ShortCutModifierUtils.java diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java index 905c5917c..11c0083ec 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/common/table/AbstractTableLayout.java @@ -9,12 +9,11 @@ package org.eclipse.hawkbit.ui.common.table; import org.eclipse.hawkbit.ui.common.detailslayout.AbstractTableDetailsLayout; +import org.eclipse.hawkbit.ui.utils.ShortCutModifierUtils; import com.vaadin.event.Action; import com.vaadin.event.Action.Handler; import com.vaadin.event.ShortcutAction; -import com.vaadin.server.Page; -import com.vaadin.server.WebBrowser; import com.vaadin.ui.Alignment; import com.vaadin.ui.Panel; import com.vaadin.ui.VerticalLayout; @@ -109,34 +108,21 @@ public abstract class AbstractTableLayout extends VerticalLayout { private static final String SELECT_ALL_TEXT = "Select All"; private final ShortcutAction selectAllAction = new ShortcutAction(SELECT_ALL_TEXT, ShortcutAction.KeyCode.A, - new int[] { ShortcutAction.ModifierKey.CTRL }); - - private final ShortcutAction selectAllMacAction = new ShortcutAction(SELECT_ALL_TEXT, ShortcutAction.KeyCode.A, - new int[] { ShortcutAction.ModifierKey.META }); + new int[] { ShortCutModifierUtils.getCtrlOrMetaModifier() }); private static final long serialVersionUID = 1L; @Override public void handleAction(final Action action, final Object sender, final Object target) { - if (!isSelecAllAction(action)) { + if (!selectAllAction.equals(action)) { return; } table.selectAll(); publishEvent(); } - private boolean isSelecAllAction(final Action action) { - return selectAllAction.equals(action) || selectAllMacAction.equals(action); - } - @Override public Action[] getActions(final Object target, final Object sender) { - - final WebBrowser webBrowser = Page.getCurrent().getWebBrowser(); - if (webBrowser.isMacOSX()) { - return new Action[] { selectAllMacAction }; - } - return new Action[] { selectAllAction }; } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/ShortCutModifierUtils.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/ShortCutModifierUtils.java new file mode 100644 index 000000000..b844caafd --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/ShortCutModifierUtils.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.ui.utils; + +import com.vaadin.event.ShortcutAction; +import com.vaadin.server.Page; +import com.vaadin.server.WebBrowser; + +/** + * On different systems there are different modifier for short cuts. This + * utility class handles the cross-platform functionality. + */ +public final class ShortCutModifierUtils { + + private ShortCutModifierUtils() { + + } + + /** + * Returns the ctrl or meta modifier depending on the platform. + * + * @return on mac return + * {@link com.vaadin.event.ShortcutAction.ModifierKey#META} other + * platform return + * {@link com.vaadin.event.ShortcutAction.ModifierKey#CTRL} + */ + public static int getCtrlOrMetaModifier() { + final WebBrowser webBrowser = Page.getCurrent().getWebBrowser(); + if (webBrowser.isMacOSX()) { + return ShortcutAction.ModifierKey.META; + } + + return ShortcutAction.ModifierKey.CTRL; + } +} From 6f5f2e798ba5c376799bb4481b37eba125f59af5 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 21 Jun 2016 15:19:26 +0200 Subject: [PATCH 25/46] add javdoc Signed-off-by: Michael Hirsch --- .../eclipse/hawkbit/simulator/AbstractSimulatedDevice.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java index c70d4f584..a2a036e1b 100644 --- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java +++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/AbstractSimulatedDevice.java @@ -96,7 +96,11 @@ public abstract class AbstractSimulatedDevice { this.pollDelaySec = pollDelaySec; } - abstract public void poll(); + /** + * Can be called by a scheduler to trigger a device polling, like in real + * scenarios devices are frequently asking for updates etc. + */ + public abstract void poll(); public int getPollDelaySec() { return pollDelaySec; From a75a022ca611f63993f98b3ad61a8839904d365a Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 21 Jun 2016 15:19:45 +0200 Subject: [PATCH 26/46] make poll-time in dialog always visible Signed-off-by: Michael Hirsch --- .../java/org/eclipse/hawkbit/simulator/ui/GenerateDialog.java | 2 -- 1 file changed, 2 deletions(-) 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 e337e86e7..272531407 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 @@ -76,7 +76,6 @@ public class GenerateDialog extends Window { pollDelayTextField = createRequiredTextfield("poll delay (sec)", new ObjectProperty(10), FontAwesome.CLOCK_O, new RangeValidator("Must be between 1 and 60", Integer.class, 1, 60)); - pollDelayTextField.setVisible(false); pollUrlTextField = createRequiredTextfield("base poll URL endpoint", "http://localhost:8080", FontAwesome.FLAG_O, new RegexpValidator( @@ -193,7 +192,6 @@ public class GenerateDialog extends Window { protocolGroup.select(Protocol.DMF_AMQP); protocolGroup.addValueChangeListener(event -> { final boolean directDeviceOptionSelected = event.getProperty().getValue().equals(Protocol.DDI_HTTP); - pollDelayTextField.setVisible(directDeviceOptionSelected); pollUrlTextField.setVisible(directDeviceOptionSelected); gatewayTokenTextField.setVisible(directDeviceOptionSelected); }); From 95ce14ffb4be218c386a6eda566a66bba5005b70 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 21 Jun 2016 15:36:53 +0200 Subject: [PATCH 27/46] write javadoc Signed-off-by: Michael Hirsch --- .../hawkbit/mgmt/client/scenarios/ConfigurableScenario.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java index 33afefa26..2cb339a1f 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java @@ -35,7 +35,9 @@ import org.springframework.beans.factory.annotation.Qualifier; /** * - * Default getting started scenario. + * A configurable scenario which runs the configured scenarios. + * + * @see {@link ClientConfigurationProperties#getScenarios()} * */ public class ConfigurableScenario { From 2e23ed3871ebec786826ab1a7091e15e75ddc21f Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 21 Jun 2016 15:37:22 +0200 Subject: [PATCH 28/46] remove scala dependency Signed-off-by: Michael Hirsch --- hawkbit-dmf-amqp/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hawkbit-dmf-amqp/pom.xml b/hawkbit-dmf-amqp/pom.xml index 322dd5047..289d97663 100644 --- a/hawkbit-dmf-amqp/pom.xml +++ b/hawkbit-dmf-amqp/pom.xml @@ -159,11 +159,6 @@ spring-context-support test - - org.scala-lang - scala-library - 2.10.4 - \ No newline at end of file From bf1ca010c7c9634e69ae8b62bfb52589da485801 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Tue, 21 Jun 2016 16:36:01 +0200 Subject: [PATCH 29/46] throw correct exception if target address violates rfc standard Signed-off-by: Michael Hirsch --- .../hawkbit/exception/SpServerError.java | 86 +++++++------------ .../InvalidTargetAddressException.java | 42 +++++++++ .../repository/jpa/model/JpaTargetInfo.java | 9 +- .../exception/ResponseExceptionHandler.java | 1 + 4 files changed, 83 insertions(+), 55 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java index 003b31cd7..7d618e234 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java @@ -24,82 +24,73 @@ public enum SpServerError { /** * */ - SP_REPO_ENTITY_ALRREADY_EXISTS("hawkbit.server.error.repo.entitiyAlreayExists", - "The given entity already exists in database"), + SP_REPO_ENTITY_ALRREADY_EXISTS("hawkbit.server.error.repo.entitiyAlreayExists", "The given entity already exists in database"), + + /** + * + */ + SP_REPO_INVALID_TARGET_ADDRESS("hawkbit.server.error.repo.invalidTargetAddress", "The target address is not well formed"), /** * */ - SP_REPO_ENTITY_NOT_EXISTS("hawkbit.server.error.repo.entitiyNotFound", - "The given entity does not exist in database"), + SP_REPO_ENTITY_NOT_EXISTS("hawkbit.server.error.repo.entitiyNotFound", "The given entity does not exist in database"), /** * */ - SP_REPO_CONCURRENT_MODIFICATION("hawkbit.server.error.repo.concurrentModification", - "The given entity has been changed by another user/session"), + SP_REPO_CONCURRENT_MODIFICATION("hawkbit.server.error.repo.concurrentModification", "The given entity has been changed by another user/session"), /** * */ - SP_REST_SORT_PARAM_SYNTAX("hawkbit.server.error.rest.param.sortParamSyntax", - "The given sort paramter is not well formed"), + SP_REST_SORT_PARAM_SYNTAX("hawkbit.server.error.rest.param.sortParamSyntax", "The given sort paramter is not well formed"), /** * */ - SP_REST_RSQL_SEARCH_PARAM_SYNTAX("hawkbit.server.error.rest.param.rsqlParamSyntax", - "The given search paramter is not well formed"), + SP_REST_RSQL_SEARCH_PARAM_SYNTAX("hawkbit.server.error.rest.param.rsqlParamSyntax", "The given search paramter is not well formed"), /** * */ - SP_REST_RSQL_PARAM_INVALID_FIELD("hawkbit.server.error.rest.param.rsqlInvalidField", - "The given search parameter field does not exist"), + SP_REST_RSQL_PARAM_INVALID_FIELD("hawkbit.server.error.rest.param.rsqlInvalidField", "The given search parameter field does not exist"), /** * */ - SP_REST_SORT_PARAM_INVALID_FIELD("hawkbit.server.error.rest.param.invalidField", - "The given sort parameter field does not exist"), + SP_REST_SORT_PARAM_INVALID_FIELD("hawkbit.server.error.rest.param.invalidField", "The given sort parameter field does not exist"), /** * */ - SP_REST_SORT_PARAM_INVALID_DIRECTION("hawkbit.server.error.rest.param.invalidDirection", - "The given sort parameter direction does not exist"), + SP_REST_SORT_PARAM_INVALID_DIRECTION("hawkbit.server.error.rest.param.invalidDirection", "The given sort parameter direction does not exist"), /** * */ - SP_REST_BODY_NOT_READABLE("hawkbit.server.error.rest.body.notReadable", - "The given request body is not well formed"), + SP_REST_BODY_NOT_READABLE("hawkbit.server.error.rest.body.notReadable", "The given request body is not well formed"), /** * */ - SP_ARTIFACT_UPLOAD_FAILED("hawkbit.server.error.artifact.uploadFailed", - "Upload of artifact failed with internal server error."), + SP_ARTIFACT_UPLOAD_FAILED("hawkbit.server.error.artifact.uploadFailed", "Upload of artifact failed with internal server error."), /** * */ - SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH("hawkbit.server.error.artifact.uploadFailed.checksum.md5.match", - "Upload of artifact failed as the provided MD5 checksum did not match with the provided artifact."), + SP_ARTIFACT_UPLOAD_FAILED_MD5_MATCH("hawkbit.server.error.artifact.uploadFailed.checksum.md5.match", "Upload of artifact failed as the provided MD5 checksum did not match with the provided artifact."), /** * */ - SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH("hawkbit.server.error.artifact.uploadFailed.checksum.sha1.match", - "Upload of artifact failed as the provided SHA1 checksum did not match with the provided artifact."), + SP_ARTIFACT_UPLOAD_FAILED_SHA1_MATCH("hawkbit.server.error.artifact.uploadFailed.checksum.sha1.match", "Upload of artifact failed as the provided SHA1 checksum did not match with the provided artifact."), /** * */ - SP_DS_CREATION_FAILED_MISSING_MODULE("hawkbit.server.error.distributionset.creationFailed.missingModule", - "Creation if Distribution Set failed as module is missing that is configured as mandatory."), + SP_DS_CREATION_FAILED_MISSING_MODULE("hawkbit.server.error.distributionset.creationFailed.missingModule", "Creation if Distribution Set failed as module is missing that is configured as mandatory."), /** * */ - SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED("hawkbit.server.error.artifact.uploadFailed.sizelimitexceeded", - "Upload of artifact failed as the file exceeds its maximum permitted size"), + SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED("hawkbit.server.error.artifact.uploadFailed.sizelimitexceeded", "Upload of artifact failed as the file exceeds its maximum permitted size"), /** * */ @@ -108,63 +99,53 @@ public enum SpServerError { /** * */ - SP_ARTIFACT_DELETE_FAILED("hawkbit.server.error.artifact.deleteFailed", - "Deletion of artifact failed with internal server error."), + SP_ARTIFACT_DELETE_FAILED("hawkbit.server.error.artifact.deleteFailed", "Deletion of artifact failed with internal server error."), /** * */ - SP_ARTIFACT_LOAD_FAILED("hawkbit.server.error.artifact.loadFailed", - "Load of artifact failed with internal server error."), + SP_ARTIFACT_LOAD_FAILED("hawkbit.server.error.artifact.loadFailed", "Load of artifact failed with internal server error."), /** * */ - SP_ACTION_STATUS_TO_MANY_ENTRIES("hawkbit.server.error.action.status.tooManyEntries", - "Too many status entries have been inserted."), + SP_ACTION_STATUS_TO_MANY_ENTRIES("hawkbit.server.error.action.status.tooManyEntries", "Too many status entries have been inserted."), /** * */ - SP_ATTRIBUTES_TO_MANY_ENTRIES("hawkbit.server.error.target.attributes.tooManyEntries", - "Too many attribute entries have been inserted."), + SP_ATTRIBUTES_TO_MANY_ENTRIES("hawkbit.server.error.target.attributes.tooManyEntries", "Too many attribute entries have been inserted."), /** * error message, which describes that the action can not be canceled cause * the action is inactive. */ - SP_ACTION_NOT_CANCELABLE("hawkbit.server.error.action.notcancelable", - "Only active actions which are in status pending are canceable."), + SP_ACTION_NOT_CANCELABLE("hawkbit.server.error.action.notcancelable", "Only active actions which are in status pending are canceable."), /** * error message, which describes that the action can not be force quit * cause the action is inactive. */ - SP_ACTION_NOT_FORCE_QUITABLE("hawkbit.server.error.action.notforcequitable", - "Only active actions which are in status pending can be force quit."), + SP_ACTION_NOT_FORCE_QUITABLE("hawkbit.server.error.action.notforcequitable", "Only active actions which are in status pending can be force quit."), /** * */ - SP_DS_INCOMPLETE("hawkbit.server.error.distributionset.incomplete", - "Distribution set is assigned to a a target that is incomplete (i.e. mandatory modules are missing)"), + SP_DS_INCOMPLETE("hawkbit.server.error.distributionset.incomplete", "Distribution set is assigned to a a target that is incomplete (i.e. mandatory modules are missing)"), /** * */ - SP_DS_TYPE_UNDEFINED("hawkbit.server.error.distributionset.type.undefined", - "Distribution set type is not yet defined. Modules cannot be added until definition."), + SP_DS_TYPE_UNDEFINED("hawkbit.server.error.distributionset.type.undefined", "Distribution set type is not yet defined. Modules cannot be added until definition."), /** * */ - SP_DS_MODULE_UNSUPPORTED("hawkbit.server.error.distributionset.modules.unsupported", - "Distribution set type does not contain the given module, i.e. is incompatible."), + SP_DS_MODULE_UNSUPPORTED("hawkbit.server.error.distributionset.modules.unsupported", "Distribution set type does not contain the given module, i.e. is incompatible."), /** * */ - SP_REPO_TENANT_NOT_EXISTS("hawkbit.server.error.repo.tenantNotExists", - "The entity cannot be inserted due the tenant does not exists"), + SP_REPO_TENANT_NOT_EXISTS("hawkbit.server.error.repo.tenantNotExists", "The entity cannot be inserted due the tenant does not exists"), /** * @@ -174,14 +155,12 @@ public enum SpServerError { /** * */ - SP_REPO_ENTITY_READ_ONLY("hawkbit.server.error.entityreadonly", - "The given entity is read only and the change cannot be completed."), + SP_REPO_ENTITY_READ_ONLY("hawkbit.server.error.entityreadonly", "The given entity is read only and the change cannot be completed."), /** * */ - SP_CONFIGURATION_VALUE_INVALID("hawkbit.server.error.configValueInvalid", - "The given configuration value is invalid."), + SP_CONFIGURATION_VALUE_INVALID("hawkbit.server.error.configValueInvalid", "The given configuration value is invalid."), /** * */ @@ -190,8 +169,7 @@ public enum SpServerError { /** * */ - SP_ROLLOUT_ILLEGAL_STATE("hawkbit.server.error.rollout.illegalstate", - "The rollout is currently in the wrong state for the current operation"); + SP_ROLLOUT_ILLEGAL_STATE("hawkbit.server.error.rollout.illegalstate", "The rollout is currently in the wrong state for the current operation"); private final String key; private final String message; 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 new file mode 100644 index 000000000..70b890483 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/InvalidTargetAddressException.java @@ -0,0 +1,42 @@ +/** + * 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.exception; + +import org.eclipse.hawkbit.exception.SpServerError; +import org.eclipse.hawkbit.exception.SpServerRtException; + +/** + * Exception which is thrown when trying to set an invalid target address. + */ +public class InvalidTargetAddressException extends SpServerRtException { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * @param message + * the message for this exception + */ + public InvalidTargetAddressException(final String message) { + super(message, SpServerError.SP_REPO_INVALID_TARGET_ADDRESS); + } + + /** + * + * @param message + * the message for this exception + * @param cause + * the cause for this exception + */ + public InvalidTargetAddressException(final String message, final Throwable cause) { + super(message, SpServerError.SP_REPO_INVALID_TARGET_ADDRESS, cause); + } +} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java index 15abc2d61..0606def4f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTargetInfo.java @@ -37,6 +37,7 @@ import javax.persistence.OneToOne; import javax.persistence.Table; import javax.persistence.Transient; +import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException; import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.model.DistributionSet; @@ -173,10 +174,16 @@ public class JpaTargetInfo implements Persistable, TargetInfo { * @throws IllegalArgumentException * If the given string violates RFC 2396 */ + @Override public void setAddress(final String address) { // check if this is a real URI if (address != null) { - URI.create(address); + try { + URI.create(address); + } catch (final IllegalArgumentException e) { + throw new InvalidTargetAddressException( + "The given address " + address + " violates the RFC-2396 specification", e); + } } this.address = address; 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 0f8da9ebe..31e4a3046 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 @@ -67,6 +67,7 @@ public class ResponseExceptionHandler { ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ROLLOUT_ILLEGAL_STATE, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_VALUE_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_KEY_INVALID, HttpStatus.BAD_REQUEST); + ERROR_TO_HTTP_STATUS.put(SpServerError.SP_REPO_INVALID_TARGET_ADDRESS, HttpStatus.BAD_REQUEST); } private static HttpStatus getStatusOrDefault(final SpServerError error) { From 7cb3b2f2ff45952ac5656dce704498be5e266151 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Tue, 21 Jun 2016 18:05:20 +0200 Subject: [PATCH 30/46] Added storage of clients correlation ID in action history. Signed-off-by: kaizimmerm --- .../eclipse/hawkbit/amqp/AmqpMessageHandlerService.java | 7 +++++++ .../hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) 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 caa11ab3d..73f9e14df 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 @@ -35,6 +35,7 @@ import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.EntityFactory; +import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.TenantNotExistException; @@ -69,6 +70,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.web.util.UriComponentsBuilder; +import com.google.common.base.Strings; import com.google.common.eventbus.EventBus; /** @@ -346,6 +348,11 @@ public class AmqpMessageHandlerService extends BaseAmqpService { final ActionStatus actionStatus = entityFactory.generateActionStatus(); actionUpdateStatus.getMessage().forEach(actionStatus::addMessage); + if (!Strings.isNullOrEmpty(message.getMessageProperties().getCorrelationIdString())) { + actionStatus.addMessage(RepositoryConstants.SERVER_MESSAGE_PREFIX + "DMF message correlation-id " + + message.getMessageProperties().getCorrelationIdString()); + } + actionStatus.setAction(action); actionStatus.setOccurredAt(System.currentTimeMillis()); 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 e93e1340f..8cd92d2bd 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 @@ -33,7 +33,6 @@ import ru.yandex.qatools.allure.annotations.Stories; @Stories("Test to generate the artifact download URL") @SpringApplicationConfiguration(classes = { AmqpTestConfiguration.class, org.eclipse.hawkbit.RepositoryApplicationConfiguration.class }) - public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB { private static final String HTTPS_LOCALHOST = "https://localhost:8080/"; From 3d049fada19db19075415125e5be8744b5d2c825 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Wed, 22 Jun 2016 09:17:35 +0200 Subject: [PATCH 31/46] Add DMF message correlation-id to action history. Signed-off-by: kaizimmerm --- .../org/eclipse/hawkbit/simulator/amqp/SenderService.java | 1 + .../src/main/resources/application.properties | 2 +- .../org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java | 5 ++--- .../org/eclipse/hawkbit/amqp/DefaultAmqpSenderService.java | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) 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 6f16ac736..f2c0e7fcb 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 @@ -58,6 +58,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()); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, address, correlationId); diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties index ac3f240a3..747e8ffe9 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties +++ b/examples/hawkbit-example-mgmt-simulator/src/main/resources/application.properties @@ -13,7 +13,7 @@ hawkbit.password=admin spring.main.show-banner=false -hawkbit.scenarios.[0].cleanRepository=true +hawkbit.scenarios.[0].cleanRepository=false hawkbit.scenarios.[0].targets=0 hawkbit.scenarios.[0].ds-name=gettingstarted-example hawkbit.scenarios.[0].distribution-sets=3 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 73f9e14df..3f42c2937 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 @@ -70,7 +70,6 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextImpl; import org.springframework.web.util.UriComponentsBuilder; -import com.google.common.base.Strings; import com.google.common.eventbus.EventBus; /** @@ -348,9 +347,9 @@ public class AmqpMessageHandlerService extends BaseAmqpService { final ActionStatus actionStatus = entityFactory.generateActionStatus(); actionUpdateStatus.getMessage().forEach(actionStatus::addMessage); - if (!Strings.isNullOrEmpty(message.getMessageProperties().getCorrelationIdString())) { + if (message.getMessageProperties().getCorrelationId().length > 0) { actionStatus.addMessage(RepositoryConstants.SERVER_MESSAGE_PREFIX + "DMF message correlation-id " - + message.getMessageProperties().getCorrelationIdString()); + + message.getMessageProperties().getCorrelationId()); } actionStatus.setAction(action); 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 afb3e7ff2..d951cce5d 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 @@ -46,6 +46,7 @@ public class DefaultAmqpSenderService implements AmqpSenderService { final String correlationId = UUID.randomUUID().toString(); final String exchange = extractExchange(replyTo); + message.getMessageProperties().setCorrelationId(correlationId.getBytes()); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, exchange, correlationId); From 837b62758a779a7fb6791f86af178b5c4230b457 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Wed, 22 Jun 2016 12:24:52 +0200 Subject: [PATCH 32/46] Removed closed todo Signed-off-by: Kai Zimmermann --- .../eclipse/hawkbit/repository/jpa/JpaControllerManagement.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index a4ca4d6ae..abe4dba03 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -253,7 +253,6 @@ public class JpaControllerManagement implements ControllerManagement { public Action addUpdateActionStatus(@NotNull final ActionStatus actionStatus) { final JpaAction action = (JpaAction) actionStatus.getAction(); - // TODO: test // if action is already closed we accept further status updates on if // permitted so by configuration. This is especially use full if the // action status feedback channel order from the device cannot be From 717a23671edfcb90f23e1ddb797d4db599036ee0 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Wed, 22 Jun 2016 12:31:35 +0200 Subject: [PATCH 33/46] Propr rabbit client version handling in parent POM. Signed-off-by: Kai Zimmermann --- hawkbit-dmf-amqp/pom.xml | 7 +------ pom.xml | 6 ++++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hawkbit-dmf-amqp/pom.xml b/hawkbit-dmf-amqp/pom.xml index 289d97663..9dd4f12aa 100644 --- a/hawkbit-dmf-amqp/pom.xml +++ b/hawkbit-dmf-amqp/pom.xml @@ -48,12 +48,7 @@ org.springframework.amqp spring-rabbit - - - com.rabbitmq - amqp-client - 3.6.2 - + org.springframework.security spring-security-web diff --git a/pom.xml b/pom.xml index f50afa0ab..8e49bd9df 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,7 @@ 5.2.4.Final 1.2.0.RELEASE 1.6.0.RELEASE + 3.6.2 0.18.0.RELEASE Fowler-SR1 @@ -526,6 +527,11 @@ org.eclipse.persistence.jpa ${eclipselink.version} + + com.rabbitmq + amqp-client + ${rabbitmq.version} + cz.jirutka.rsql From 9226f514d230e7af7d48c24df1a6a7211afce419 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 22 Jun 2016 13:36:22 +0200 Subject: [PATCH 34/46] add spring security eval expression for system_monitor permission Signed-off-by: Michael Hirsch --- .../org/eclipse/hawkbit/im/authentication/SpPermission.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 ce6bc7c40..139954538 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 @@ -396,6 +396,12 @@ public final class SpPermission { public static final String HAS_AUTH_TENANT_CONFIGURATION = HAS_AUTH_PREFIX + TENANT_CONFIGURATION + HAS_AUTH_SUFFIX; + /** + * Spring security eval hasAuthority expression to check if spring + * context contains {@link SpPermission#SYSTEM_MONITOR} + */ + public static final String HAS_AUTH_SYSTEM_MONITOR = HAS_AUTH_PREFIX + SYSTEM_MONITOR + HAS_AUTH_SUFFIX; + private SpringEvalExpressions() { // utility class } From aef2e3450a6278f94ec087c3f1ae441c34c9c16b Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 22 Jun 2016 15:46:43 +0200 Subject: [PATCH 35/46] remove special health security check because this can be made with spring security out-of-the box Signed-off-by: Michael Hirsch --- .../SecurityManagedConfiguration.java | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) 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 0b68246ff..1e4dbfb27 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 @@ -271,20 +271,6 @@ public class SecurityManagedConfiguration { return filterRegBean; } - /** - * Security configuration for the REST management API of the health url. - */ - @Configuration - @Order(310) - public static class HealthSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(final HttpSecurity http) throws Exception { - http.regexMatcher("/system/health").csrf().disable().httpBasic().and().sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS); - } - } - /** * Security configuration for the REST management API. */ @@ -310,7 +296,7 @@ public class SecurityManagedConfiguration { final BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint(); basicAuthEntryPoint.setRealmName(springSecurityProperties.getBasic().getRealm()); - HttpSecurity httpSec = http.regexMatcher("\\/rest.*|\\/system.*").csrf().disable(); + HttpSecurity httpSec = http.regexMatcher("\\/rest.*|\\/system/admin.*").csrf().disable(); if (springSecurityProperties.isRequireSsl()) { httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and(); } @@ -337,9 +323,7 @@ public class SecurityManagedConfiguration { SessionManagementFilter.class) .authorizeRequests().anyRequest().authenticated() .antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/admin/**") - .hasAnyAuthority(SpPermission.SYSTEM_ADMIN) - .antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/**") - .hasAnyAuthority(SpPermission.SYSTEM_DIAG); + .hasAnyAuthority(SpPermission.SYSTEM_ADMIN); httpSec.httpBasic().and().exceptionHandling().authenticationEntryPoint(basicAuthEntryPoint); } From 11f2232247276409643e7c4ebedcb8f482cd5061 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 22 Jun 2016 15:47:38 +0200 Subject: [PATCH 36/46] add prefixed ROLE_ to granted authorities to work with out-of-the-box spring security Signed-off-by: Michael Hirsch --- .../org/eclipse/hawkbit/im/authentication/PermissionUtils.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/PermissionUtils.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/PermissionUtils.java index ae8b604bb..98cde9642 100644 --- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/PermissionUtils.java +++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/im/authentication/PermissionUtils.java @@ -36,6 +36,9 @@ public final class PermissionUtils { for (final String role : roles) { authorities.add(new SimpleGrantedAuthority(role)); + // add spring security ROLE authority which is indicated by the + // `ROLE_` prefix + authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); } return authorities; From 27005b1ae74eab7e88ae116c5c24f9e0813022ad Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Wed, 22 Jun 2016 17:33:09 +0200 Subject: [PATCH 37/46] fix test Signed-off-by: Michael Hirsch --- .../eclipse/hawkbit/im/authentication/PermissionTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/PermissionTest.java b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/PermissionTest.java index bca7fd1c1..2c948206e 100644 --- a/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/PermissionTest.java +++ b/hawkbit-security-core/src/test/java/org/eclipse/hawkbit/im/authentication/PermissionTest.java @@ -36,7 +36,8 @@ public final class PermissionTest { final Collection allAuthorities = SpPermission.getAllAuthorities(); final List allAuthoritiesList = PermissionUtils.createAllAuthorityList(); assertThat(allAuthorities).hasSize(allPermission); - assertThat(allAuthoritiesList).hasSize(allPermission); + // times 2 because we add also all authorities as prefix 'ROLE_'; + assertThat(allAuthoritiesList).hasSize(allPermission * 2); assertThat(allAuthoritiesList.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) .containsAll(allAuthorities); @@ -46,7 +47,8 @@ public final class PermissionTest { .getAllAuthorities(SpPermission.SYSTEM_ADMIN, SpPermission.SYSTEM_DIAG, SpPermission.SYSTEM_MONITOR)); assertThat(authoritiesWithoutSystem).hasSize(permissionWithoutSystem); - assertThat(authoritiesListWithoutSystem).hasSize(permissionWithoutSystem); + // times 2 because we add also all authorities as prefix 'ROLE_'; + assertThat(authoritiesListWithoutSystem).hasSize(permissionWithoutSystem * 2); assertThat(authoritiesListWithoutSystem.stream().map(authority -> authority.getAuthority()) .collect(Collectors.toList())).containsAll(authoritiesWithoutSystem); From fa2477f5cb1fe83f2840caa358b9396226c94c1b Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Thu, 23 Jun 2016 09:02:05 +0200 Subject: [PATCH 38/46] Fixed nullpointer exception and optimized the code here and there. Signed-off-by: kaizimmerm --- .../scenarios/ConfigurableScenario.java | 23 +++++++++------- .../client/scenarios/upload/ArtifactFile.java | 9 +++++-- .../upload/FeignMultipartEncoder.java | 16 +++-------- .../amqp/AmqpMessageHandlerService.java | 27 ++++++++++++------- .../jpa/JpaControllerManagement.java | 4 +-- 5 files changed, 42 insertions(+), 37 deletions(-) diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java index 2cb339a1f..a09459e07 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/ConfigurableScenario.java @@ -42,6 +42,8 @@ import org.springframework.beans.factory.annotation.Qualifier; */ public class ConfigurableScenario { + private static final int PAGE_SIZE = 100; + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurableScenario.class); private final MgmtDistributionSetClientResource distributionSetResource; @@ -109,25 +111,25 @@ public class ConfigurableScenario { private void deleteSoftwareModules() { PagedList modules; do { - modules = softwareModuleResource.getSoftwareModules(0, 100, null, null).getBody(); + modules = softwareModuleResource.getSoftwareModules(0, PAGE_SIZE, null, null).getBody(); modules.getContent().forEach(module -> softwareModuleResource.deleteSoftwareModule(module.getModuleId())); - } while (modules.getTotal() > 100); + } while (modules.getTotal() > PAGE_SIZE); } private void deleteDistributionSets() { PagedList distributionSets; do { - distributionSets = distributionSetResource.getDistributionSets(0, 100, null, null).getBody(); + distributionSets = distributionSetResource.getDistributionSets(0, PAGE_SIZE, null, null).getBody(); distributionSets.getContent().forEach(set -> distributionSetResource.deleteDistributionSet(set.getDsId())); - } while (distributionSets.getTotal() > 100); + } while (distributionSets.getTotal() > PAGE_SIZE); } private void deleteTargets() { PagedList targets; do { - targets = targetResource.getTargets(0, 100, null, null).getBody(); + targets = targetResource.getTargets(0, PAGE_SIZE, null, null).getBody(); targets.getContent().forEach(target -> targetResource.deleteTarget(target.getControllerId())); - } while (targets.getTotal() > 100); + } while (targets.getTotal() > PAGE_SIZE); } private void runRollouts(final Scenario scenario) { @@ -217,10 +219,11 @@ public class ConfigurableScenario { private void createTargets(final Scenario scenario) { LOGGER.info("Creating {} targets", scenario.getTargets()); - for (int i = 0; i < scenario.getTargets() / 100; i++) { - targetResource.createTargets(new TargetBuilder().controllerId(scenario.getTargetName()) - .address(scenario.getTargetAddress()).buildAsList(i * 100, - (i + 1) * 100 > scenario.getTargets() ? (scenario.getTargets() - (i * 100)) : 100)); + for (int i = 0; i < (scenario.getTargets() / PAGE_SIZE); i++) { + targetResource.createTargets( + new TargetBuilder().controllerId(scenario.getTargetName()).address(scenario.getTargetAddress()) + .buildAsList(i * PAGE_SIZE, (i + 1) * PAGE_SIZE > scenario.getTargets() + ? (scenario.getTargets() - (i * PAGE_SIZE)) : PAGE_SIZE)); } LOGGER.info("Creating {} targets -> Done", scenario.getTargets()); diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java index adad1fe77..379455580 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/ArtifactFile.java @@ -12,11 +12,16 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.Optional; import org.springframework.util.Assert; import org.springframework.util.FileCopyUtils; import org.springframework.web.multipart.MultipartFile; +/** + * Implementation for {@link MultipartFile} for hawkBit artifact upload. + * + */ public class ArtifactFile implements MultipartFile { private final String name; @@ -55,9 +60,9 @@ public class ArtifactFile implements MultipartFile { final byte[] content) { Assert.hasLength(name, "Name must not be null"); this.name = name; - this.originalFilename = originalFilename != null ? originalFilename : ""; + this.originalFilename = Optional.ofNullable(originalFilename).orElse(""); this.contentType = contentType; - this.content = content != null ? content : new byte[0]; + this.content = Optional.ofNullable(content).orElse(new byte[0]); } @Override diff --git a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java index 00424c5e5..5d1e43e96 100644 --- a/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java +++ b/examples/hawkbit-example-mgmt-simulator/src/main/java/org/eclipse/hawkbit/mgmt/client/scenarios/upload/FeignMultipartEncoder.java @@ -40,7 +40,7 @@ public class FeignMultipartEncoder implements Encoder { private final HttpHeaders multipartHeaders = new HttpHeaders(); private final HttpHeaders jsonHeaders = new HttpHeaders(); - public static final Charset UTF_8 = Charset.forName("UTF-8"); + private static final Charset UTF_8 = Charset.forName("UTF-8"); public FeignMultipartEncoder() { multipartHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); @@ -48,11 +48,8 @@ public class FeignMultipartEncoder implements Encoder { } @Override - public void encode(final Object object, final Type bodyType, final RequestTemplate template) - throws EncodeException { - + public void encode(final Object object, final Type bodyType, final RequestTemplate template) { encodeMultipartFormRequest(object, template); - } private void encodeMultipartFormRequest(final Object value, final RequestTemplate template) { @@ -66,8 +63,7 @@ public class FeignMultipartEncoder implements Encoder { } @SuppressWarnings("unchecked") - private void encodeRequest(final Object value, final HttpHeaders requestHeaders, final RequestTemplate template) - throws EncodeException { + private void encodeRequest(final Object value, final HttpHeaders requestHeaders, final RequestTemplate template) { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final HttpOutputMessage dummyRequest = new HttpOutputMessageImpl(outputStream, requestHeaders); try { @@ -150,12 +146,6 @@ public class FeignMultipartEncoder implements Encoder { return this.filename; } - @Override - public InputStream getInputStream() throws IOException, IllegalStateException { - return super.getInputStream(); // To change body of generated - // methods, choose Tools | Templates. - } - @Override public long contentLength() throws IOException { return size; 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 3f42c2937..27cbc0f69 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 @@ -14,6 +14,7 @@ import java.util.Collections; import java.util.List; import java.util.UUID; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.eclipse.hawkbit.api.HostnameResolver; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; @@ -344,16 +345,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService { final ActionUpdateStatus actionUpdateStatus = convertMessage(message, ActionUpdateStatus.class); final Action action = checkActionExist(message, actionUpdateStatus); - final ActionStatus actionStatus = entityFactory.generateActionStatus(); - actionUpdateStatus.getMessage().forEach(actionStatus::addMessage); - - if (message.getMessageProperties().getCorrelationId().length > 0) { - actionStatus.addMessage(RepositoryConstants.SERVER_MESSAGE_PREFIX + "DMF message correlation-id " - + message.getMessageProperties().getCorrelationId()); - } - - actionStatus.setAction(action); - actionStatus.setOccurredAt(System.currentTimeMillis()); + final ActionStatus actionStatus = createActionStatus(message, actionUpdateStatus, action); switch (actionUpdateStatus.getActionStatus()) { case DOWNLOAD: @@ -391,6 +383,21 @@ public class AmqpMessageHandlerService extends BaseAmqpService { } } + private ActionStatus createActionStatus(final Message message, final ActionUpdateStatus actionUpdateStatus, + final Action action) { + final ActionStatus actionStatus = entityFactory.generateActionStatus(); + actionUpdateStatus.getMessage().forEach(actionStatus::addMessage); + + if (ArrayUtils.isNotEmpty(message.getMessageProperties().getCorrelationId())) { + actionStatus.addMessage(RepositoryConstants.SERVER_MESSAGE_PREFIX + "DMF message correlation-id " + + message.getMessageProperties().getCorrelationId()); + } + + actionStatus.setAction(action); + actionStatus.setOccurredAt(System.currentTimeMillis()); + return actionStatus; + } + private Action getUpdateActionStatus(final ActionStatus actionStatus) { if (actionStatus.getStatus().equals(Status.CANCELED)) { return controllerManagement.addCancelActionStatus(actionStatus); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index abe4dba03..b9dfce105 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -253,8 +253,8 @@ public class JpaControllerManagement implements ControllerManagement { public Action addUpdateActionStatus(@NotNull final ActionStatus actionStatus) { final JpaAction action = (JpaAction) actionStatus.getAction(); - // if action is already closed we accept further status updates on if - // permitted so by configuration. This is especially use full if the + // if action is already closed we accept further status updates if + // permitted so by configuration. This is especially useful if the // action status feedback channel order from the device cannot be // guaranteed. However, if an action is closed we do not accept further // close messages. From bb1d3a2668df55761c56f63177f3871ad6dd6f85 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Thu, 23 Jun 2016 09:15:40 +0200 Subject: [PATCH 39/46] Remove whitespace. Signed-off-by: kaizimmerm --- hawkbit-dmf-amqp/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hawkbit-dmf-amqp/pom.xml b/hawkbit-dmf-amqp/pom.xml index 9dd4f12aa..c2ed7c213 100644 --- a/hawkbit-dmf-amqp/pom.xml +++ b/hawkbit-dmf-amqp/pom.xml @@ -48,7 +48,7 @@ org.springframework.amqp spring-rabbit - + org.springframework.security spring-security-web From 0a36f23bb33d47de6532941119aad2a3f82931f1 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Fri, 24 Jun 2016 12:09:23 +0200 Subject: [PATCH 40/46] retrieve target-security-token with system-context permission Signed-off-by: Michael Hirsch --- .../eclipse/hawkbit/amqp/AmqpMessageHandlerService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 27cbc0f69..8c1b359a6 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 @@ -47,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.util.IpUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -105,6 +106,9 @@ public class AmqpMessageHandlerService extends BaseAmqpService { @Autowired private EntityFactory entityFactory; + @Autowired + private SystemSecurityContext systemSecurityContext; + /** * Constructor. * @@ -313,9 +317,10 @@ public class AmqpMessageHandlerService extends BaseAmqpService { final DistributionSet distributionSet = action.getDistributionSet(); final List softwareModuleList = controllerManagement .findSoftwareModulesByDistributionSet(distributionSet); + final String targetSecurityToken = systemSecurityContext.runAsSystem(() -> target.getSecurityToken()); eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(), target.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress(), - target.getSecurityToken())); + targetSecurityToken)); } From 128585c95e87651237b3542c1d29a37bb4e6ef03 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Fri, 24 Jun 2016 12:38:46 +0200 Subject: [PATCH 41/46] fix test Signed-off-by: Michael Hirsch --- .../eclipse/hawkbit/amqp/AmqpMessageHandlerService.java | 3 +++ .../hawkbit/amqp/AmqpMessageHandlerServiceTest.java | 7 +++++++ 2 files changed, 10 insertions(+) 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 8c1b359a6..36f90adae 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 @@ -478,4 +478,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService { this.entityFactory = entityFactory; } + void setSystemSecurityContext(final SystemSecurityContext systemSecurityContext) { + this.systemSecurityContext = systemSecurityContext; + } } 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 338feea62..7ef51d961 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 @@ -52,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.LocalArtifact; import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.TargetInfo; import org.eclipse.hawkbit.security.SecurityTokenGenerator; +import org.eclipse.hawkbit.security.SystemSecurityContext; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -112,6 +113,9 @@ public class AmqpMessageHandlerServiceTest { @Mock private RabbitTemplate rabbitTemplate; + @Mock + private SystemSecurityContext systemSecurityContextMock; + @Before public void before() throws Exception { messageConverter = new Jackson2JsonMessageConverter(); @@ -124,6 +128,7 @@ public class AmqpMessageHandlerServiceTest { amqpMessageHandlerService.setHostnameResolver(hostnameResolverMock); amqpMessageHandlerService.setEventBus(eventBus); amqpMessageHandlerService.setEntityFactory(entityFactoryMock); + amqpMessageHandlerService.setSystemSecurityContext(systemSecurityContextMock); } @@ -367,6 +372,8 @@ public class AmqpMessageHandlerServiceTest { when(controllerManagementMock.findSoftwareModulesByDistributionSet(Matchers.any())) .thenReturn(softwareModuleList); + when(systemSecurityContextMock.runAsSystem(anyObject())).thenReturn("securityToken"); + final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT); messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name()); final ActionUpdateStatus actionUpdateStatus = createActionUpdateStatus(ActionStatus.FINISHED, 23L); From 23cb62b9d9b7e537fa81aaed75ef2f780ee92827 Mon Sep 17 00:00:00 2001 From: kaizimmerm Date: Fri, 24 Jun 2016 13:59:19 +0200 Subject: [PATCH 42/46] Fix scheduled executor, auth exchange and simulator poll. Signed-off-by: kaizimmerm --- .../simulator/DeviceSimulatorUpdater.java | 3 +- .../simulator/SimulatedDeviceFactory.java | 2 +- .../simulator/SimulationController.java | 4 - .../hawkbit/simulator/SimulatorStartup.java | 5 - .../simulator/amqp/AmqpConfiguration.java | 10 +- .../AsyncConfigurerThreadpoolProperties.java | 13 +++ .../scheduling/ExecutorAutoConfiguration.java | 50 +++++----- .../main/resources/hawkbitdefaults.properties | 3 +- .../hawkbit/amqp/AmqpConfiguration.java | 93 +++++++++++++------ .../amqp/AmqpMessageHandlerService.java | 25 ++++- .../eclipse/hawkbit/amqp/AmqpProperties.java | 24 ++++- .../hawkbit/AmqpTestConfiguration.java | 9 +- .../AmqpControllerAuthenticationTest.java | 19 ++-- .../amqp/AmqpMessageHandlerServiceTest.java | 19 ++-- .../hawkbit/dmf/amqp/api/AmqpSettings.java | 2 + .../hawkbit/dmf/amqp/api/MessageType.java | 5 - .../test/util/TestConfiguration.java | 4 +- 17 files changed, 185 insertions(+), 105 deletions(-) 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 0931f6f3e..81237beb7 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 @@ -99,7 +99,8 @@ public class DeviceSimulatorUpdater { // plug and play - non existing device will be auto created if (device == null) { - device = repository.add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, -1, null, null)); + device = repository + .add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, 1800, null, null)); } device.setProgress(0.0); 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 35829c673..8d5c5e0b1 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 @@ -45,7 +45,7 @@ public class SimulatedDeviceFactory { */ public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant, final Protocol protocol) { - return createSimulatedDevice(id, tenant, protocol, 30, null, null); + return createSimulatedDevice(id, tenant, protocol, 1800, null, null); } /** 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 3bd6b41f2..43f954c00 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 @@ -86,10 +86,6 @@ public class SimulationController { final String deviceId = name + i; repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint), gatewayToken)); - - if (protocol == Protocol.DMF_AMQP) { - spSenderService.createOrUpdateThing(tenant, deviceId); - } } return ResponseEntity.ok("Updated " + amount + " DMF connected targets!"); 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 19367a9d4..486eb4b5e 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,6 @@ package org.eclipse.hawkbit.simulator; import java.net.MalformedURLException; import java.net.URL; -import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol; import org.eclipse.hawkbit.simulator.amqp.SpSenderService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,10 +53,6 @@ public class SimulatorStartup implements ApplicationListener arguments = getDeadLetterExchangeArgs(); arguments.putAll(getTTLMaxArgs()); - return QueueBuilder.nonDurable(amqpProperties.getReceiverConnectorQueueFromSp()).withArguments(arguments) - .build(); + return QueueBuilder.nonDurable(amqpProperties.getReceiverConnectorQueueFromSp()).autoDelete() + .withArguments(arguments).build(); } /** @@ -133,12 +133,12 @@ public class AmqpConfiguration { */ @Bean public FanoutExchange exchangeQueueToConnector() { - return new FanoutExchange(amqpProperties.getSenderForSpExchange()); + return new FanoutExchange(amqpProperties.getSenderForSpExchange(), false, true); } /** * Create the Binding - * {@link AmqpConfiguration#receiverConnectorQueueFromSp()} to + * {@link AmqpConfiguration#receiverConnectorQueueFromHawkBit()} to * {@link AmqpConfiguration#exchangeQueueToConnector()}. * * @return the binding and create the queue and exchange @@ -165,7 +165,7 @@ public class AmqpConfiguration { */ @Bean public FanoutExchange exchangeDeadLetter() { - return new FanoutExchange(amqpProperties.getDeadLetterExchange()); + return new FanoutExchange(amqpProperties.getDeadLetterExchange(), false, true); } /** diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java index 4425c7278..d6f3ca430 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java @@ -32,6 +32,11 @@ public class AsyncConfigurerThreadpoolProperties { */ private Integer maxthreads = 20; + /** + * Core processing threads for scheduled event executor. + */ + private Integer schedulerThreads = 3; + /** * When the number of threads is greater than the core, this is the maximum * time that excess idle threads will wait for new tasks before terminating. @@ -70,4 +75,12 @@ public class AsyncConfigurerThreadpoolProperties { this.idletimeout = idletimeout; } + public Integer getSchedulerThreads() { + return schedulerThreads; + } + + public void setSchedulerThreads(final Integer schedulerThreads) { + this.schedulerThreads = schedulerThreads; + } + } diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java index 0aeaf75bb..917e4e4ef 100644 --- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java +++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java @@ -11,6 +11,8 @@ package org.eclipse.hawkbit.autoconfigure.scheduling; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy; @@ -24,9 +26,12 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.TaskExecutor; +import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; +import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService; +import org.springframework.security.concurrent.DelegatingSecurityContextScheduledExecutorService; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -45,20 +50,28 @@ public class ExecutorAutoConfiguration { /** * @return ExecutorService with security context availability in thread - * execution.. + * execution. + */ + @Bean(destroyMethod = "shutdown") + @ConditionalOnMissingBean + public ExecutorService asyncExecutor() { + return new DelegatingSecurityContextExecutorService(threadPoolExecutor()); + } + + /** + * @return {@link TaskExecutor} for task execution */ @Bean @ConditionalOnMissingBean - public Executor asyncExecutor() { - return new DelegatingSecurityContextExecutor(threadPoolExecutor()); + public TaskExecutor taskExecutor() { + return new ConcurrentTaskExecutor(asyncExecutor()); } /** * @return central ThreadPoolExecutor for general purpose multi threaded * operations. Tries an orderly shutdown when destroyed. */ - @Bean(destroyMethod = "shutdown") - public ThreadPoolExecutor threadPoolExecutor() { + private ThreadPoolExecutor threadPoolExecutor() { final BlockingQueue blockingQueue = new ArrayBlockingQueue<>( asyncConfigurerProperties.getQueuesize()); return new ThreadPoolExecutor(asyncConfigurerProperties.getCorethreads(), @@ -92,31 +105,24 @@ public class ExecutorAutoConfiguration { } /** - * @return {@link TaskExecutor} for task execution + * @return {@link ScheduledExecutorService} with security context + * availability in thread execution. */ - @Bean - @ConditionalOnMissingBean - public TaskExecutor taskExecutor() { - return new ConcurrentTaskExecutor(asyncExecutor()); - } - - /** - * @return {@link ScheduledExecutorService} based on - * {@link #threadPoolTaskScheduler()}. - */ - @Bean + @Bean(destroyMethod = "shutdown") @ConditionalOnMissingBean public ScheduledExecutorService scheduledExecutorService() { - return threadPoolTaskScheduler().getScheduledExecutor(); + return new DelegatingSecurityContextScheduledExecutorService( + Executors.newScheduledThreadPool(asyncConfigurerProperties.getSchedulerThreads(), + new ThreadFactoryBuilder().setNameFormat("central-scheduled-executor-pool-%d").build())); } /** - * @return {@link ThreadPoolTaskScheduler} for scheduled operations. + * @return {@link TaskScheduler} for task execution */ @Bean @ConditionalOnMissingBean - public ThreadPoolTaskScheduler threadPoolTaskScheduler() { - return new ThreadPoolTaskScheduler(); + public TaskScheduler taskScheduler() { + return new ConcurrentTaskScheduler(scheduledExecutorService()); } } diff --git a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties index 9c197fbb3..cb7793168 100644 --- a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties +++ b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties @@ -41,4 +41,5 @@ hawkbit.controller.minPollingTime=00:00:30 # Configuration for RabbitMQ integration hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter_ttl hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter -hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver \ No newline at end of file +hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver +hawkbit.dmf.rabbitmq.authenticationReceiverQueue=authentication_receiver 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 c26b5547e..ae25d0086 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 @@ -8,8 +8,11 @@ */ package org.eclipse.hawkbit.amqp; +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadPoolExecutor; import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings; import org.slf4j.Logger; @@ -18,6 +21,7 @@ import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.FanoutExchange; import org.springframework.amqp.core.Queue; +import org.springframework.amqp.core.QueueBuilder; import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; @@ -51,10 +55,6 @@ public class AmqpConfiguration { @Autowired private AmqpDeadletterProperties amqpDeadletterProperties; - @Autowired - @Qualifier("threadPoolExecutor") - private ThreadPoolExecutor threadPoolExecutor; - @Autowired private ConnectionFactory rabbitConnectionFactory; @@ -66,8 +66,8 @@ public class AmqpConfiguration { private AmqpProperties amqpProperties; @Autowired - @Qualifier("threadPoolExecutor") - private ThreadPoolExecutor threadPoolExecutor; + @Qualifier("asyncExecutor") + private Executor threadPoolExecutor; @Autowired private ScheduledExecutorService scheduledExecutorService; @@ -145,26 +145,71 @@ public class AmqpConfiguration { } /** - * Create the sp receiver queue. + * Create the DMF API receiver queue for * * @return the receiver queue */ @Bean - public Queue receiverQueue() { + public Queue dmfReceiverQueue() { return new Queue(amqpProperties.getReceiverQueue(), true, false, false, amqpDeadletterProperties.getDeadLetterExchangeArgs(amqpProperties.getDeadLetterExchange())); } /** - * Create the dead letter fanout exchange. + * Create the DMF API receiver queue for authentication requests called by + * 3rd party artifact storages for download authorization by devices. + * + * @return the receiver queue + */ + @Bean + public Queue authenticationReceiverQueue() { + return QueueBuilder.nonDurable(amqpProperties.getAuthenticationReceiverQueue()).autoDelete() + .withArguments(getTTLMaxArgsAuthenticationQueue()).build(); + } + + /** + * Create DMF exchange. * * @return the fanout exchange */ @Bean - public FanoutExchange senderExchange() { + public FanoutExchange dmfSenderExchange() { return new FanoutExchange(AmqpSettings.DMF_EXCHANGE); } + /** + * Create the Binding {@link AmqpConfiguration#dmfReceiverQueue()} to + * {@link AmqpConfiguration#dmfSenderExchange()}. + * + * @return the binding and create the queue and exchange + */ + @Bean + public Binding bindDmfSenderExchangeToDmfQueue() { + return BindingBuilder.bind(dmfReceiverQueue()).to(dmfSenderExchange()); + } + + /** + * Create authentication exchange. + * + * @return the fanout exchange + */ + @Bean + public FanoutExchange authenticationExchange() { + return new FanoutExchange(AmqpSettings.AUTHENTICATION_EXCHANGE, false, true); + } + + /** + * Create the Binding + * {@link AmqpConfiguration#authenticationReceiverQueue()} to + * {@link AmqpConfiguration#authenticationExchange()}. + * + * @return the binding and create the queue and exchange + */ + @Bean + public Binding bindAuthenticationSenderExchangeToAuthenticationQueue() { + return BindingBuilder.bind(authenticationReceiverQueue()).to(authenticationExchange()); + } + /** * Create dead letter queue. * @@ -181,29 +226,18 @@ public class AmqpConfiguration { * @return the fanout exchange */ @Bean - public FanoutExchange exchangeDeadLetter() { + public FanoutExchange deadLetterExchange() { return new FanoutExchange(amqpProperties.getDeadLetterExchange()); } /** - * Create the Binding deadLetterQueue to exchangeDeadLetter. + * Create the Binding deadLetterQueue to deadLetterExchange. * * @return the binding */ @Bean - public Binding bindDeadLetterQueueToLwm2mExchange() { - return BindingBuilder.bind(deadLetterQueue()).to(exchangeDeadLetter()); - } - - /** - * Create the Binding {@link AmqpConfiguration#receiverQueue()} to - * {@link AmqpConfiguration#senderExchange()}. - * - * @return the binding and create the queue and exchange - */ - @Bean - public Binding bindSenderExchangeToSpQueue() { - return BindingBuilder.bind(receiverQueue()).to(senderExchange()); + public Binding bindDeadLetterQueueToDeadLetterExchange() { + return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()); } /** @@ -245,4 +279,11 @@ public class AmqpConfiguration { return containerFactory; } + private static Map getTTLMaxArgsAuthenticationQueue() { + final Map args = new HashMap<>(); + args.put("x-message-ttl", Duration.ofSeconds(30).toMillis()); + args.put("x-max-length", 1_000); + return args; + } + } 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 27cbc0f69..7d4e08144 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 @@ -116,7 +116,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService { } /** - * Method to handle all incoming amqp messages. + * Method to handle all incoming DMF amqp messages. * * @param message * incoming message @@ -133,6 +133,12 @@ public class AmqpMessageHandlerService extends BaseAmqpService { return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost()); } + @RabbitListener(queues = "${hawkbit.dmf.rabbitmq.authenticationReceiverQueue}", containerFactory = "listenerContainerFactory") + public Message onAuthenticationRequest(final Message message, + @Header(MessageHeaderKey.TENANT) final String tenant) { + return onAuthenticationRequest(message); + } + public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) { checkContentTypeJson(message); final SecurityContext oldContext = SecurityContextHolder.getContext(); @@ -149,8 +155,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService { final EventTopic eventTopic = EventTopic.valueOf(topicValue); handleIncomingEvent(message, eventTopic); break; - case AUTHENTIFICATION: - return handleAuthentifiactionMessage(message); + default: logAndThrowMessageError(message, "No handle method was found for the given message type."); } @@ -164,6 +169,20 @@ public class AmqpMessageHandlerService extends BaseAmqpService { return null; } + public Message onAuthenticationRequest(final Message message) { + checkContentTypeJson(message); + final SecurityContext oldContext = SecurityContextHolder.getContext(); + try { + return handleAuthentifiactionMessage(message); + } catch (final IllegalArgumentException ex) { + throw new AmqpRejectAndDontRequeueException("Invalid message!", ex); + } catch (final TenantNotExistException teex) { + throw new AmqpRejectAndDontRequeueException(teex); + } finally { + SecurityContextHolder.setContext(oldContext); + } + } + private Message handleAuthentifiactionMessage(final Message message) { final DownloadResponse authentificationResponse = new DownloadResponse(); final MessageProperties messageProperties = message.getMessageProperties(); diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java index ace1fefa2..888b204e7 100644 --- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java +++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java @@ -31,10 +31,16 @@ public class AmqpProperties { private String deadLetterExchange = "dmf.connector.deadletter"; /** - * DMF API receiving queue. + * DMF API receiving queue for EVENT or THING_CREATED message. */ private String receiverQueue = "dmf_receiver"; + /** + * Authentication request called by 3rd party artifact storages for download + * authorizations. + */ + private String authenticationReceiverQueue = "authentication_receiver"; + /** * Missing queue fatal. */ @@ -62,6 +68,14 @@ public class AmqpProperties { */ private int initialConcurrentConsumers = 3; + public String getAuthenticationReceiverQueue() { + return authenticationReceiverQueue; + } + + public void setAuthenticationReceiverQueue(final String authenticationReceiverQueue) { + this.authenticationReceiverQueue = authenticationReceiverQueue; + } + public int getPrefetchCount() { return prefetchCount; } @@ -147,10 +161,6 @@ public class AmqpProperties { return receiverQueue; } - public void setReceiverQueue(final String receiverQueue) { - this.receiverQueue = receiverQueue; - } - public int getRequestedHeartBeat() { return requestedHeartBeat; } @@ -159,4 +169,8 @@ public class AmqpProperties { this.requestedHeartBeat = requestedHeartBeat; } + public void setReceiverQueue(final String receiverQueue) { + this.receiverQueue = receiverQueue; + } + } diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/AmqpTestConfiguration.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/AmqpTestConfiguration.java index 075313a19..467c650be 100644 --- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/AmqpTestConfiguration.java +++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/AmqpTestConfiguration.java @@ -31,7 +31,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; -import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; +import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService; import com.google.common.util.concurrent.ThreadFactoryBuilder; @@ -78,18 +78,17 @@ public class AmqpTestConfiguration { * @return ExecutorService with security context availability in thread * execution.. */ - @Bean + @Bean(destroyMethod = "shutdown") @ConditionalOnMissingBean public Executor asyncExecutor() { - return new DelegatingSecurityContextExecutor(threadPoolExecutor()); + return new DelegatingSecurityContextExecutorService(threadPoolExecutor()); } /** * @return central ThreadPoolExecutor for general purpose multi threaded * operations. Tries an orderly shutdown when destroyed. */ - @Bean(destroyMethod = "shutdown") - public ThreadPoolExecutor threadPoolExecutor() { + private ThreadPoolExecutor threadPoolExecutor() { final BlockingQueue blockingQueue = new ArrayBlockingQueue<>(10); final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS, blockingQueue, new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build()); 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 881260579..4e08e1852 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 @@ -158,7 +158,7 @@ public class AmqpControllerAuthenticationTest { @Test @Description("Tests authentication message without principal") public void testAuthenticationMessageBadCredantialsWithoutPricipal() { - final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); + final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, FileResource.sha1("12345")); @@ -166,8 +166,7 @@ public class AmqpControllerAuthenticationTest { messageProperties); // test - final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), - TENANT, "vHost"); + final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message); // verify final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); @@ -178,7 +177,7 @@ public class AmqpControllerAuthenticationTest { @Test @Description("Tests authentication message without wrong credential") public void testAuthenticationMessageBadCredantialsWithWrongCredential() { - final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); + final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, FileResource.sha1("12345")); when(tenantConfigurationManagement.getConfigurationValue( @@ -189,8 +188,7 @@ public class AmqpControllerAuthenticationTest { messageProperties); // test - final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), - TENANT, "vHost"); + final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message); // verify final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); @@ -201,7 +199,7 @@ public class AmqpControllerAuthenticationTest { @Test @Description("Tests authentication message successfull") public void testSuccessfullMessageAuthentication() { - final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); + final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID, FileResource.sha1("12345")); when(tenantConfigurationManagement.getConfigurationValue( @@ -212,8 +210,7 @@ public class AmqpControllerAuthenticationTest { messageProperties); // test - final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), - TENANT, "vHost"); + final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message); // verify final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); @@ -232,7 +229,9 @@ public class AmqpControllerAuthenticationTest { private MessageProperties createMessageProperties(final MessageType type, final String replyTo) { final MessageProperties messageProperties = new MessageProperties(); - messageProperties.setHeader(MessageHeaderKey.TYPE, type.name()); + if (type != null) { + messageProperties.setHeader(MessageHeaderKey.TYPE, type.name()); + } messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT); messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON); messageProperties.setReplyTo(replyTo); 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 338feea62..43d7980df 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 @@ -273,14 +273,13 @@ public class AmqpMessageHandlerServiceTest { @Test @Description("Tests that an download request is denied for an artifact which does not exists") public void authenticationRequestDeniedForArtifactWhichDoesNotExists() { - final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION); + final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, messageProperties); // test - final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), - TENANT, "vHost"); + final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message); // verify final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); @@ -292,7 +291,7 @@ public class AmqpMessageHandlerServiceTest { @Test @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(MessageType.AUTHENTIFICATION); + final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, messageProperties); @@ -303,8 +302,7 @@ public class AmqpMessageHandlerServiceTest { .thenThrow(EntityNotFoundException.class); // test - final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), - TENANT, "vHost"); + final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message); // verify final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); @@ -316,7 +314,7 @@ public class AmqpMessageHandlerServiceTest { @Test @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(MessageType.AUTHENTIFICATION); + final MessageProperties messageProperties = createMessageProperties(null); final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.sha1("12345")); final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken, messageProperties); @@ -334,8 +332,7 @@ public class AmqpMessageHandlerServiceTest { when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost")); // test - final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(), - TENANT, "vHost"); + final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message); // verify final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage); @@ -411,7 +408,9 @@ public class AmqpMessageHandlerServiceTest { private MessageProperties createMessageProperties(final MessageType type, final String replyTo) { final MessageProperties messageProperties = new MessageProperties(); - messageProperties.setHeader(MessageHeaderKey.TYPE, type.name()); + if (type != null) { + messageProperties.setHeader(MessageHeaderKey.TYPE, type.name()); + } messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT); messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON); messageProperties.setReplyTo(replyTo); diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/AmqpSettings.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/AmqpSettings.java index 40ba04419..364f36aa5 100644 --- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/AmqpSettings.java +++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/AmqpSettings.java @@ -18,6 +18,8 @@ public final class AmqpSettings { public static final String DMF_EXCHANGE = "dmf.exchange"; + public static final String AUTHENTICATION_EXCHANGE = "authentication.exchange"; + private AmqpSettings() { } diff --git a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java index 8cca32b06..e66a0c8c6 100644 --- a/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java +++ b/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/amqp/api/MessageType.java @@ -26,9 +26,4 @@ public enum MessageType { */ THING_CREATED, - /** - * The authentication type. - */ - AUTHENTIFICATION, - } diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestConfiguration.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestConfiguration.java index e6a8e7686..3a7a2f73d 100644 --- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestConfiguration.java +++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestConfiguration.java @@ -31,7 +31,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.data.domain.AuditorAware; import org.springframework.scheduling.annotation.AsyncConfigurer; -import org.springframework.security.concurrent.DelegatingSecurityContextExecutor; +import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import com.google.common.eventbus.AsyncEventBus; @@ -99,7 +99,7 @@ public class TestConfiguration implements AsyncConfigurer { @Bean public Executor asyncExecutor() { - return new DelegatingSecurityContextExecutor(Executors.newSingleThreadExecutor()); + return new DelegatingSecurityContextExecutorService(Executors.newSingleThreadExecutor()); } @Bean From 2150f45bded5c45729c7bf6b655f4768a1202380 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Fri, 24 Jun 2016 14:51:18 +0200 Subject: [PATCH 43/46] use SecurityContext as thread local because it's delegated throug threads Signed-off-by: Michael Hirsch --- .../security/SecurityContextTenantAware.java | 101 +++++++++++++----- .../security/SystemSecurityContext.java | 18 ++-- 2 files changed, 88 insertions(+), 31 deletions(-) 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 2d8ac52df..e548acb7a 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 @@ -8,13 +8,15 @@ */ package org.eclipse.hawkbit.security; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.Collection; import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.context.SecurityContextImpl; /** * A {@link TenantAware} implemenation which retrieves the ID of the tenant from @@ -28,9 +30,6 @@ import org.springframework.security.core.context.SecurityContextHolder; */ public class SecurityContextTenantAware implements TenantAware { - private static final ThreadLocal TENANT_THREAD_LOCAL = new ThreadLocal<>(); - private static final ThreadLocal RUN_AS_DEPTH = new ThreadLocal<>(); - /* * (non-Javadoc) * @@ -38,9 +37,6 @@ public class SecurityContextTenantAware implements TenantAware { */ @Override public String getCurrentTenant() { - if (TENANT_THREAD_LOCAL.get() != null) { - return TENANT_THREAD_LOCAL.get(); - } final SecurityContext context = SecurityContextHolder.getContext(); if (context.getAuthentication() != null) { final Object authDetails = context.getAuthentication().getDetails(); @@ -51,29 +47,84 @@ public class SecurityContextTenantAware implements TenantAware { return null; } - /* - * (non-Javadoc) - * - * @see hawkbit.server.tenancy.TenantAware#runAsTenant(java.lang.String, - * java.util.concurrent.Callable) - */ @Override public T runAsTenant(final String tenant, final TenantRunner callable) { - AtomicInteger runAsDepth = RUN_AS_DEPTH.get(); - if (runAsDepth == null) { - runAsDepth = new AtomicInteger(1); - RUN_AS_DEPTH.set(runAsDepth); - } else { - runAsDepth.incrementAndGet(); - } - TENANT_THREAD_LOCAL.set(tenant); + final SecurityContext originalContext = SecurityContextHolder.getContext(); try { + SecurityContextHolder.setContext(buildSecurityContext(tenant)); return callable.run(); } finally { - if (runAsDepth.decrementAndGet() <= 0) { - RUN_AS_DEPTH.remove(); - TENANT_THREAD_LOCAL.remove(); - } + SecurityContextHolder.setContext(originalContext); + } + } + + private SecurityContext buildSecurityContext(final String tenant) { + final SecurityContextImpl securityContext = new SecurityContextImpl(); + securityContext.setAuthentication( + new AuthenticationDelegate(SecurityContextHolder.getContext().getAuthentication(), tenant)); + return securityContext; + } + + private class AuthenticationDelegate implements Authentication { + private static final long serialVersionUID = 1L; + + private final Authentication delegate; + private final TenantAwareAuthenticationDetails tenantAwareAuthenticationDetails; + + private AuthenticationDelegate(final Authentication delegate, final String tenant) { + this.delegate = delegate; + tenantAwareAuthenticationDetails = new TenantAwareAuthenticationDetails(tenant, false); + + } + + @Override + public boolean equals(final Object another) { + return delegate.equals(another); + } + + @Override + public String toString() { + return delegate.toString(); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + public Collection getAuthorities() { + return delegate.getAuthorities(); + } + + @Override + public Object getCredentials() { + return delegate.getCredentials(); + } + + @Override + public Object getDetails() { + return tenantAwareAuthenticationDetails; + } + + @Override + public Object getPrincipal() { + return delegate.getPrincipal(); + } + + @Override + public boolean isAuthenticated() { + return delegate.isAuthenticated(); + } + + @Override + public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException { + delegate.setAuthenticated(isAuthenticated); } } } 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 78fb5818d..c0ecb8ceb 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 @@ -72,7 +72,7 @@ public class SystemSecurityContext { logger.debug("entering system code execution"); return tenantAware.runAsTenant(tenantAware.getCurrentTenant(), () -> { try { - setSystemContext(); + setSystemContext(oldContext); return callable.call(); } catch (final Exception e) { throw Throwables.propagate(e); @@ -93,9 +93,10 @@ public class SystemSecurityContext { return SecurityContextHolder.getContext().getAuthentication() instanceof SystemCodeAuthentication; } - private static void setSystemContext() { + private static void setSystemContext(final SecurityContext oldContext) { + final Authentication oldAuthentication = oldContext.getAuthentication(); final SecurityContextImpl securityContextImpl = new SecurityContextImpl(); - securityContextImpl.setAuthentication(new SystemCodeAuthentication()); + securityContextImpl.setAuthentication(new SystemCodeAuthentication(oldAuthentication)); SecurityContextHolder.setContext(securityContextImpl); } @@ -104,6 +105,11 @@ public class SystemSecurityContext { private static final long serialVersionUID = 1L; private static final List AUTHORITIES = Collections .singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE)); + private final Authentication oldAuthentication; + + private SystemCodeAuthentication(final Authentication oldAuthentication) { + this.oldAuthentication = oldAuthentication; + } @Override public String getName() { @@ -117,17 +123,17 @@ public class SystemSecurityContext { @Override public Object getCredentials() { - return null; + return oldAuthentication != null ? oldAuthentication.getCredentials() : null; } @Override public Object getDetails() { - return null; + return oldAuthentication != null ? oldAuthentication.getDetails() : null; } @Override public Object getPrincipal() { - return null; + return oldAuthentication != null ? oldAuthentication.getPrincipal() : null; } @Override From a5d84a47e070df13cfc8624330fa2f018dce0a86 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Fri, 24 Jun 2016 14:58:26 +0200 Subject: [PATCH 44/46] code beautify Signed-off-by: Michael Hirsch --- .../hawkbit/security/SecurityContextTenantAware.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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 e548acb7a..4b5fe7224 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 @@ -24,9 +24,6 @@ import org.springframework.security.core.context.SecurityContextImpl; * {@link Authentication#getDetails()} which holds the * {@link TenantAwareAuthenticationDetails} object. * - * - * - * */ public class SecurityContextTenantAware implements TenantAware { @@ -65,6 +62,11 @@ public class SecurityContextTenantAware implements TenantAware { return securityContext; } + /** + * An {@link Authentication} implementation to delegate to an existing + * {@link Authentication} object except setting the details specifically for + * a specific tenant. + */ private class AuthenticationDelegate implements Authentication { private static final long serialVersionUID = 1L; @@ -74,7 +76,6 @@ public class SecurityContextTenantAware implements TenantAware { private AuthenticationDelegate(final Authentication delegate, final String tenant) { this.delegate = delegate; tenantAwareAuthenticationDetails = new TenantAwareAuthenticationDetails(tenant, false); - } @Override From 82bdaf53ed9610a976a8441a9f663eb5db828b11 Mon Sep 17 00:00:00 2001 From: SirWayne Date: Fri, 24 Jun 2016 15:12:24 +0200 Subject: [PATCH 45/46] Fix wrong multi part exception message in response. Hardening all exception message and classes in exception handler for reponses Signed-off-by: SirWayne --- .../hawkbit/exception/SpServerError.java | 4 -- .../resource/MgmtSoftwareModuleResource.java | 32 ++++----- .../MultiPartFileUploadException.java | 30 ++++++++ .../exception/ResponseExceptionHandler.java | 72 ++++++++++--------- 4 files changed, 82 insertions(+), 56 deletions(-) create mode 100644 hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiPartFileUploadException.java diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java index 7d618e234..5acd11463 100644 --- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java +++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/exception/SpServerError.java @@ -87,10 +87,6 @@ public enum SpServerError { */ SP_DS_CREATION_FAILED_MISSING_MODULE("hawkbit.server.error.distributionset.creationFailed.missingModule", "Creation if Distribution Set failed as module is missing that is configured as mandatory."), - /** - * - */ - SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED("hawkbit.server.error.artifact.uploadFailed.sizelimitexceeded", "Upload of artifact failed as the file exceeds its maximum permitted size"), /** * */ diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java index b4f1e8adb..b475c473f 100644 --- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java +++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtSoftwareModuleResource.java @@ -68,28 +68,24 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi { @RequestParam(value = "md5sum", required = false) final String md5Sum, @RequestParam(value = "sha1sum", required = false) final String sha1Sum) { - Artifact result; - if (!file.isEmpty()) { - String fileName = optionalFileName; - - if (null == fileName) { - fileName = file.getOriginalFilename(); - } - - try { - result = artifactManagement.createLocalArtifact(file.getInputStream(), softwareModuleId, fileName, - md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(), - false, file.getContentType()); - } catch (final IOException e) { - LOG.error("Failed to store artifact", e); - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); - } - } else { + if (file.isEmpty()) { return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } + String fileName = optionalFileName; - return new ResponseEntity<>(MgmtSoftwareModuleMapper.toResponse(result), HttpStatus.CREATED); + if (fileName == null) { + fileName = file.getOriginalFilename(); + } + try { + final Artifact result = artifactManagement.createLocalArtifact(file.getInputStream(), softwareModuleId, + fileName, md5Sum == null ? null : md5Sum.toLowerCase(), + sha1Sum == null ? null : sha1Sum.toLowerCase(), false, file.getContentType()); + return new ResponseEntity<>(MgmtSoftwareModuleMapper.toResponse(result), HttpStatus.CREATED); + } catch (final IOException e) { + LOG.error("Failed to store artifact", e); + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } } @Override 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 new file mode 100644 index 000000000..e37786e19 --- /dev/null +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/MultiPartFileUploadException.java @@ -0,0 +1,30 @@ +/** + * 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.exception; + +import org.eclipse.hawkbit.exception.SpServerError; +import org.eclipse.hawkbit.exception.SpServerRtException; + +/** + * Thrown if a multi part exception occurred. + * + */ +public final class MultiPartFileUploadException extends SpServerRtException { + + private static final long serialVersionUID = 1L; + + /** + * @param cause + * for the exception + */ + public MultiPartFileUploadException(final Throwable cause) { + super(cause.getMessage(), SpServerError.SP_ARTIFACT_UPLOAD_FAILED, cause); + } + +} 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 31e4a3046..13e214c45 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 @@ -13,9 +13,10 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; -import org.apache.tomcat.util.http.fileupload.FileUploadBase.FileSizeLimitExceededException; +import org.apache.tomcat.util.http.fileupload.FileUploadException; import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.exception.SpServerRtException; +import org.eclipse.hawkbit.repository.exception.MultiPartFileUploadException; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,10 +29,6 @@ import org.springframework.web.multipart.MultipartException; /** * General controller advice for exception handling. - * - * - * - * */ @ControllerAdvice public class ResponseExceptionHandler { @@ -89,14 +86,11 @@ public class ResponseExceptionHandler { @ExceptionHandler(SpServerRtException.class) public ResponseEntity handleSpServerRtExceptions(final HttpServletRequest request, final Exception ex) { - LOG.debug("Handling exception of request {}", request.getRequestURL()); - final ExceptionInfo response = new ExceptionInfo(); + logRequest(request, ex); + final ExceptionInfo response = createExceptionInfo(ex); final HttpStatus responseStatus; - response.setMessage(ex.getMessage()); - response.setExceptionClass(ex.getClass().getName()); if (ex instanceof SpServerRtException) { responseStatus = getStatusOrDefault(((SpServerRtException) ex).getError()); - response.setErrorCode(((SpServerRtException) ex).getError().getKey()); } else { responseStatus = DEFAULT_RESPONSE_STATUS; } @@ -118,11 +112,8 @@ public class ResponseExceptionHandler { @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity handleHttpMessageNotReadableException(final HttpServletRequest request, final Exception ex) { - LOG.debug("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL()); - final ExceptionInfo response = new ExceptionInfo(); - response.setErrorCode(SpServerError.SP_REST_BODY_NOT_READABLE.getKey()); - response.setMessage(SpServerError.SP_REST_BODY_NOT_READABLE.getMessage()); - response.setExceptionClass(MessageNotReadableException.class.getName()); + logRequest(request, ex); + final ExceptionInfo response = createExceptionInfo(new MessageNotReadableException()); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } @@ -139,35 +130,48 @@ public class ResponseExceptionHandler { * as entity. */ @ExceptionHandler(MultipartException.class) - public ResponseEntity handleFileLimitExceededException(final HttpServletRequest request, + public ResponseEntity handleMultipartException(final HttpServletRequest request, final Exception ex) { - LOG.debug("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL()); - final ExceptionInfo response = new ExceptionInfo(); + logRequest(request, ex); - if (searchForCause(ex, FileSizeLimitExceededException.class)) { - response.setErrorCode(SpServerError.SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED.getKey()); - response.setMessage(SpServerError.SP_ARTIFACT_UPLOAD_FILE_LIMIT_EXCEEDED.getMessage()); - response.setExceptionClass(FileSizeLimitExceededException.class.getName()); - } else { - response.setErrorCode(SpServerError.SP_ARTIFACT_UPLOAD_FAILED.getKey()); - response.setMessage(SpServerError.SP_ARTIFACT_UPLOAD_FAILED.getMessage()); - response.setExceptionClass(MultipartException.class.getName()); + Throwable responseCause = ex; + + final Throwable searchForCause = searchForCause(ex, FileUploadException.class); + if (searchForCause != null) { + responseCause = searchForCause; } + final ExceptionInfo response = createExceptionInfo(new MultiPartFileUploadException(responseCause)); return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } - private static boolean searchForCause(final Throwable t, final Class lookFor) { - if (t != null && t.getCause() != null) { - if (t.getCause().getClass().isAssignableFrom(lookFor)) { - return true; - } else { - return searchForCause(t.getCause(), lookFor); - } + private void logRequest(final HttpServletRequest request, final Exception ex) { + LOG.debug("Handling exception {} of request {}", ex.getClass().getName(), request.getRequestURL()); + } + + private static Throwable searchForCause(final Throwable t, final Class lookFor) { + if (t == null || t.getCause() == null) { + return null; } - return false; + final Throwable cause = t.getCause(); + + if (cause.getClass().equals(lookFor)) { + return cause; + } + return searchForCause(cause, lookFor); + } + + private ExceptionInfo createExceptionInfo(final Exception ex) { + final ExceptionInfo response = new ExceptionInfo(); + response.setMessage(ex.getMessage()); + response.setExceptionClass(ex.getClass().getName()); + if (ex instanceof SpServerRtException) { + response.setErrorCode(((SpServerRtException) ex).getError().getKey()); + } + + return response; } } From a5ee3018209cff815299f67679453cf182230368 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Sat, 25 Jun 2016 12:29:12 +0200 Subject: [PATCH 46/46] update javadoc Signed-off-by: Michael Hirsch --- .../main/java/org/eclipse/hawkbit/amqp/AmqpConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ae25d0086..538f82213 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 @@ -145,7 +145,7 @@ public class AmqpConfiguration { } /** - * Create the DMF API receiver queue for + * Create the DMF API receiver queue for retrieving DMF messages. * * @return the receiver queue */