Merge branch 'master' into

feature_MECS-86_tenant_specific_polling_configuration

Conflicts:
	hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java
	hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java
	hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java
	hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentficationTest.java
	hawkbit-repository/src/test/resources/application-test.properties


Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
SirWayne
2016-03-09 13:29:40 +01:00
143 changed files with 2716 additions and 1669 deletions

View File

@@ -14,12 +14,11 @@ import java.util.Set;
import javax.servlet.http.Cookie;
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.ui.components.SPUIErrorHandler;
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
import org.eclipse.hawkbit.ui.menu.DashboardMenu;
import org.eclipse.hawkbit.ui.menu.DashboardMenuItem;
import org.eclipse.hawkbit.ui.push.EventPushStrategy;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
@@ -28,14 +27,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.SessionEventBus;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.vaadin.annotations.Title;
import com.vaadin.navigator.Navigator;
import com.vaadin.navigator.View;
@@ -45,9 +38,6 @@ import com.vaadin.server.ClientConnector.DetachListener;
import com.vaadin.server.Responsive;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinService;
import com.vaadin.server.VaadinSession;
import com.vaadin.server.VaadinSession.State;
import com.vaadin.server.WrappedSession;
import com.vaadin.spring.navigator.SpringViewProvider;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
@@ -71,6 +61,8 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
private static final String EMPTY_VIEW = "";
private EventPushStrategy pushStrategy;
@Autowired
private SpringViewProvider viewProvider;
@@ -92,69 +84,37 @@ public class HawkbitUI extends DefaultHawkbitUI implements DetachListener {
protected transient EventBus.SessionEventBus eventBus;
/**
* An {@link com.google.common.eventbus.EventBus} subscriber which
* subscribes {@link EntityEvent} from the repository to dispatch these
* events to the UI {@link SessionEventBus}.
*
* @param event
* the entity event which has been published from the repository
* Default constructor.
*/
@Subscribe
@AllowConcurrentEvents
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
final VaadinSession session = getSession();
if (session == null || session.getState() != State.OPEN) {
return;
}
final WrappedSession wrappedSession = session.getSession();
if (wrappedSession == null) {
return;
}
final SecurityContext userContext = (SecurityContext) wrappedSession
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
if (!eventSecurityCheck(userContext, event)) {
return;
}
final SecurityContext oldContext = SecurityContextHolder.getContext();
try {
access(new DispatcherRunnable(eventBus, session, userContext, event));
} finally {
SecurityContextHolder.setContext(oldContext);
}
public HawkbitUI() {
// is empty, is ok.
}
protected boolean eventSecurityCheck(final SecurityContext userContext,
final org.eclipse.hawkbit.eventbus.event.Event event) {
if (userContext != null && userContext.getAuthentication() != null) {
final Object tenantAuthenticationDetails = userContext.getAuthentication().getDetails();
if (tenantAuthenticationDetails instanceof TenantAwareAuthenticationDetails) {
return ((TenantAwareAuthenticationDetails) tenantAuthenticationDetails).getTenant()
.equalsIgnoreCase(event.getTenant());
}
}
return false;
/**
* Constructor taking the push strategy.
*
* @param pushStrategy
* the strategy to push events from the backend to the UI
*/
public HawkbitUI(final EventPushStrategy pushStrategy) {
this.pushStrategy = pushStrategy;
}
/*
* (non-Javadoc)
*
* @see
* com.vaadin.server.ClientConnector.DetachListener#detach(com.vaadin.server
* .ClientConnector. DetachEvent)
*/
@Override
public void detach(final DetachEvent event) {
LOG.info("ManagementUI is detached uiid - {}", getUIId());
eventBus.unsubscribe(this);
if (pushStrategy != null) {
pushStrategy.clean();
}
}
@Override
protected void init(final VaadinRequest vaadinRequest) {
LOG.info("ManagementUI init starts uiid - {}", getUI().getUIId());
if (pushStrategy != null) {
pushStrategy.init(getUI());
}
addDetachListener(this);
SpringContextHelper.setContext(context);

View File

@@ -0,0 +1,162 @@
/**
* 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;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* Properties for Management UI customization.
*
*/
@Component
@ConfigurationProperties("hawkbit.server.ui")
public class UiProperties {
private final Links links = new Links();
private final Login login = new Login();
private final Demo demo = new Demo();
public Login getLogin() {
return login;
}
public Links getLinks() {
return links;
}
public Demo getDemo() {
return demo;
}
/**
* Demo account login information.
*
*/
public static class Demo {
/**
* Demo tenant.
*/
private String tenant = "DEFAULT";
/**
* Demo user name.
*/
private String user = "admin";
/**
* Demo user password.
*/
private String password = "admin";
public String getTenant() {
return tenant;
}
public void setTenant(final String tenant) {
this.tenant = tenant;
}
public String getUser() {
return user;
}
public void setUser(final String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
}
/**
* Links to potentially other systems (e.g. support, user management etc.).
*
*/
public static class Links {
/**
* Link to product support.
*/
private String support = "";
/**
* Link to request a system account, access.
*/
private String requestAccount = "";
/**
* Link to user management.
*/
private String userManagement = "";
public String getSupport() {
return support;
}
public void setSupport(final String support) {
this.support = support;
}
public String getRequestAccount() {
return requestAccount;
}
public void setRequestAccount(final String requestAccount) {
this.requestAccount = requestAccount;
}
public String getUserManagement() {
return userManagement;
}
public void setUserManagement(final String userManagement) {
this.userManagement = userManagement;
}
}
/**
* Configuration of login view.
*
*/
public static class Login {
private final Cookie cookie = new Cookie();
public Cookie getCookie() {
return cookie;
}
/**
* Cookie configuration for login credential cookie.
*
*/
public static class Cookie {
/**
* Secure cookie enabled.
*/
private boolean secure = true;
public boolean isSecure() {
return secure;
}
public void setSecure(final boolean secure) {
this.secure = secure;
}
}
}
}

View File

@@ -438,17 +438,17 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
if (permChecker.hasUpdateDistributionPermission()) {
optionValues.add(updateType.getValue());
}
createOptionGroup(optionValues);
createOptionGroupByValues(optionValues);
}
private void singleMultiOptionGroup() {
final List<String> optionValues = new ArrayList<>();
optionValues.add(singleAssign.getValue());
optionValues.add(multiAssign.getValue());
assignOptionGroup(optionValues);
assignOptionGroupByValues(optionValues);
}
private void createOptionGroup(final List<String> tagOptions) {
private void createOptionGroupByValues(final List<String> tagOptions) {
createOptiongroup = new OptionGroup("", tagOptions);
createOptiongroup.setStyleName(ValoTheme.OPTIONGROUP_SMALL);
createOptiongroup.addStyleName("custom-option-group");
@@ -458,7 +458,7 @@ public class CreateUpdateSoftwareTypeLayout extends CustomComponent implements C
}
}
private void assignOptionGroup(final List<String> tagOptions) {
private void assignOptionGroupByValues(final List<String> tagOptions) {
assignOptiongroup = new OptionGroup("", tagOptions);
assignOptiongroup.setStyleName(ValoTheme.OPTIONGROUP_SMALL);
assignOptiongroup.addStyleName("custom-option-group");

View File

@@ -50,9 +50,9 @@ public class ArtifactUploadState implements Serializable {
private boolean swTypeFilterClosed = Boolean.FALSE;
private boolean isSwModuleTableMaximized = Boolean.FALSE;
private boolean swModuleTableMaximized = Boolean.FALSE;
private boolean isArtifactDetailsMaximized = Boolean.FALSE;
private boolean artifactDetailsMaximized = Boolean.FALSE;
private final Set<String> selectedDeleteSWModuleTypes = new HashSet<>();
@@ -152,15 +152,15 @@ public class ArtifactUploadState implements Serializable {
* @return the isSwModuleTableMaximized
*/
public boolean isSwModuleTableMaximized() {
return isSwModuleTableMaximized;
return swModuleTableMaximized;
}
/**
* @param isSwModuleTableMaximized
* the isSwModuleTableMaximized to set
*/
public void setSwModuleTableMaximized(final boolean isSwModuleTableMaximized) {
this.isSwModuleTableMaximized = isSwModuleTableMaximized;
public void setSwModuleTableMaximized(final boolean swModuleTableMaximized) {
this.swModuleTableMaximized = swModuleTableMaximized;
}
public Set<String> getSelectedDeleteSWModuleTypes() {
@@ -171,15 +171,15 @@ public class ArtifactUploadState implements Serializable {
* @return the isArtifactDetailsMaximized
*/
public boolean isArtifactDetailsMaximized() {
return isArtifactDetailsMaximized;
return artifactDetailsMaximized;
}
/**
* @param isArtifactDetailsMaximized
* the isArtifactDetailsMaximized to set
*/
public void setArtifactDetailsMaximized(final boolean isArtifactDetailsMaximized) {
this.isArtifactDetailsMaximized = isArtifactDetailsMaximized;
public void setArtifactDetailsMaximized(final boolean artifactDetailsMaximized) {
this.artifactDetailsMaximized = artifactDetailsMaximized;
}
/**

View File

@@ -78,7 +78,7 @@ public class TargetTagToken extends AbstractTargetTagToken {
}
private TargetTagAssigmentResult toggleAssignment(final String tagNameSelected) {
final Set<String> targetList = new HashSet<String>();
final Set<String> targetList = new HashSet<>();
targetList.add(selectedTarget.getControllerId());
final TargetTagAssigmentResult result = targetManagement.toggleTagAssignment(targetList, tagNameSelected);
uinotification.displaySuccess(HawkbitCommonUtil.getTargetTagAssigmentMsg(tagNameSelected, result, i18n));
@@ -102,7 +102,7 @@ public class TargetTagToken extends AbstractTargetTagToken {
/* To Be Done : this implementation will vary in views */
private List<String> getClickedTagList() {
return new ArrayList<String>();
return new ArrayList<>();
}
@Override

View File

@@ -38,11 +38,9 @@ public class ProxyTarget extends Target {
private TargetIdName targetIdName;
private Long createdAt;
private String assignedDistNameVersion;
private String assignedDistNameVersion = null;
private String installedDistNameVersion = null;
private String installedDistNameVersion;
private String pollStatusToolTip;
@@ -251,22 +249,6 @@ public class ProxyTarget extends Target {
this.installedDistributionSet = installedDistributionSet;
}
/**
* @return the createdAt
*/
@Override
public Long getCreatedAt() {
return createdAt;
}
/**
* @param createdAt
* the createdAt to set
*/
public void setCreatedAt(final Long createdAt) {
this.createdAt = createdAt;
}
/**
* @return the targetIdName
*/

View File

@@ -555,10 +555,10 @@ public class CreateUpdateDistSetTypeLayout extends CustomComponent implements Co
if (permChecker.hasUpdateDistributionPermission()) {
optionValues.add(updateDistType.getValue());
}
createOptionGroup(optionValues);
createOptionGroupByValues(optionValues);
}
private void createOptionGroup(final List<String> typeOptions) {
private void createOptionGroupByValues(final List<String> typeOptions) {
createOptiongroup = new OptionGroup("", typeOptions);
createOptiongroup.setId(SPUIDefinitions.CREATE_OPTION_GROUP_DISTRIBUTION_SET_TYPE_ID);
createOptiongroup.addStyleName(ValoTheme.OPTIONGROUP_SMALL);

View File

@@ -62,9 +62,9 @@ public class ManageDistUIState implements Serializable {
private final Map<Long, String> deleteSofwareModulesList = new HashMap<>();
private boolean isSwModuleTableMaximized = Boolean.FALSE;
private boolean swModuleTableMaximized = Boolean.FALSE;
private boolean isDsTableMaximized = Boolean.FALSE;
private boolean dsTableMaximized = Boolean.FALSE;
private final Map<String, SoftwareModuleIdName> assignedSoftwareModuleDetails = new HashMap<>();
@@ -219,7 +219,7 @@ public class ManageDistUIState implements Serializable {
* @return boolean
*/
public boolean isDsTableMaximized() {
return isDsTableMaximized;
return dsTableMaximized;
}
/***
@@ -227,8 +227,8 @@ public class ManageDistUIState implements Serializable {
*
* @param isDsModuleTableMaximized
*/
public void setDsTableMaximized(final boolean isDsModuleTableMaximized) {
isDsTableMaximized = isDsModuleTableMaximized;
public void setDsTableMaximized(final boolean dsModuleTableMaximized) {
dsTableMaximized = dsModuleTableMaximized;
}
public Map<String, SoftwareModuleIdName> getAssignedSoftwareModuleDetails() {
@@ -239,15 +239,15 @@ public class ManageDistUIState implements Serializable {
* @return the isSwModuleTableMaximized
*/
public boolean isSwModuleTableMaximized() {
return isSwModuleTableMaximized;
return swModuleTableMaximized;
}
/**
* @param isSwModuleTableMaximized
* the isSwModuleTableMaximized to set
*/
public void setSwModuleTableMaximized(final boolean isSwModuleTableMaximized) {
this.isSwModuleTableMaximized = isSwModuleTableMaximized;
public void setSwModuleTableMaximized(final boolean swModuleTableMaximized) {
this.swModuleTableMaximized = swModuleTableMaximized;
}
/**

View File

@@ -15,16 +15,14 @@ import javax.servlet.http.Cookie;
import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator;
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.documentation.DocumentationPageLink;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
import org.eclipse.hawkbit.util.SPInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
@@ -61,7 +59,7 @@ import com.vaadin.ui.themes.ValoTheme;
*/
@SpringView(name = "")
@UIScope
public class LoginView extends VerticalLayout implements View, EnvironmentAware {
public class LoginView extends VerticalLayout implements View {
private static final String LOGIN_TEXTFIELD = "login-textfield";
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class);
@@ -76,7 +74,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
private I18N i18n;
@Autowired
private transient SPInfo spInfo;
private transient UiProperties uiProperties;
@Autowired
private transient MultitenancyIndicator multiTenancyIndicator;
@@ -86,9 +84,6 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
private PasswordField password;
private Button signin;
private Boolean secureCookie = Boolean.TRUE;
private String userManagementLoginUrl;
void loginAuthenticationFailedNotification() {
final Notification notification = new Notification(i18n.get("notification.login.failed.title"));
notification.setDescription(i18n.get("notification.login.failed.description"));
@@ -119,7 +114,8 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
final URI spURI = Page.getCurrent().getLocation();
final String lookForDemoFragment = spURI.toString();
if (lookForDemoFragment.contains("?demo")) {
login(spInfo.getDemoTenant(), spInfo.getDemoUser(), spInfo.getDemoPassword(), false);
login(uiProperties.getDemo().getTenant(), uiProperties.getDemo().getUser(),
uiProperties.getDemo().getPassword(), false);
}
final Component loginForm = buildLoginForm();
@@ -243,18 +239,18 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
links.addComponent(demoLink);
demoLink.addStyleName(ValoTheme.LINK_SMALL);
if (spInfo.getRequestAccountEmail() != null) {
if (!uiProperties.getLinks().getRequestAccount().isEmpty()) {
final Link requestAccountLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_REQUESTACCOUNT,
i18n.get("link.requestaccount.name"), spInfo.getRequestAccountEmail(), FontAwesome.SHOPPING_CART,
"", linkStyle, true);
i18n.get("link.requestaccount.name"), uiProperties.getLinks().getRequestAccount(),
FontAwesome.SHOPPING_CART, "", linkStyle, true);
links.addComponent(requestAccountLink);
requestAccountLink.addStyleName(ValoTheme.LINK_SMALL);
}
if (userManagementLoginUrl != null) {
if (!uiProperties.getLinks().getUserManagement().isEmpty()) {
final Link userManagementLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_USERMANAGEMENT,
i18n.get("link.usermanagement.name"), userManagementLoginUrl, FontAwesome.USERS, "_blank",
linkStyle, true);
i18n.get("link.usermanagement.name"), uiProperties.getLinks().getUserManagement(),
FontAwesome.USERS, "_blank", linkStyle, true);
links.addComponent(userManagementLink);
userManagementLink.addStyleName(ValoTheme.LINK_SMALL);
}
@@ -315,7 +311,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
// 100 days
tenantCookie.setMaxAge(3600 * 24 * 100);
tenantCookie.setHttpOnly(true);
tenantCookie.setSecure(secureCookie);
tenantCookie.setSecure(uiProperties.getLogin().getCookie().isSecure());
VaadinService.getCurrentResponse().addCookie(tenantCookie);
}
@@ -324,7 +320,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
// 100 days
usernameCookie.setMaxAge(3600 * 24 * 100);
usernameCookie.setHttpOnly(true);
usernameCookie.setSecure(secureCookie);
usernameCookie.setSecure(uiProperties.getLogin().getCookie().isSecure());
VaadinService.getCurrentResponse().addCookie(usernameCookie);
}
@@ -368,16 +364,4 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
loginAuthenticationFailedNotification();
}
}
/*
* (non-Javadoc)
*
* @see org.springframework.context.EnvironmentAware#setEnvironment(org.
* springframework.core.env. Environment)
*/
@Override
public void setEnvironment(final Environment environment) {
secureCookie = environment.getProperty("hawkbit.server.ui.login.cookie.secure", Boolean.class, Boolean.TRUE);
userManagementLoginUrl = environment.getProperty("hawkbit.server.im.login.url", String.class);
}
}

View File

@@ -16,6 +16,7 @@ import java.util.StringJoiner;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.model.Action;
@@ -43,6 +44,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
@@ -417,10 +420,10 @@ public class ActionHistoryTable extends TreeTable implements Handler {
final org.eclipse.hawkbit.repository.model.Action action = deploymentManagement
.findActionWithDetails(actionId);
final Pageable pageReq = new PageRequest(0, 1000);
final Page<ActionStatus> actionStatusList = deploymentManagement
.findActionStatusMessagesByActionInDescOrder(pageReq, action,
managementUIState.isActionHistoryMaximized());
final Pageable pageReq = new PageRequest(0, 1000,
new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName()));
final Page<ActionStatus> actionStatusList = deploymentManagement.findActionStatusByAction(pageReq, action,
managementUIState.isActionHistoryMaximized());
final List<ActionStatus> content = actionStatusList.getContent();
/*
* Since the recent action status and messages are already

View File

@@ -94,8 +94,8 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
@Autowired
private transient TenantMetaDataRepository tenantMetaDataRepository;
private Button saveDistribution;
private Button discardDistribution;
private Button saveDistributionBtn;
private Button discardDistributionBtn;
private TextField distNameTextField;
private TextField distVersionTextField;
private Label madatoryLabel;
@@ -103,7 +103,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
private CheckBox reqMigStepCheckbox;
private ComboBox distsetTypeNameComboBox;
private boolean editDistribution = Boolean.FALSE;
private Long editDistId = null;
private Long editDistId;
private Window addDistributionWindow;
private String originalDistName;
private String originalDistVersion;
@@ -131,9 +131,9 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
final HorizontalLayout buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeFull();
buttonsLayout.setStyleName("dist-buttons-horz-layout");
buttonsLayout.addComponents(saveDistribution, discardDistribution);
buttonsLayout.setComponentAlignment(saveDistribution, Alignment.BOTTOM_LEFT);
buttonsLayout.setComponentAlignment(discardDistribution, Alignment.BOTTOM_RIGHT);
buttonsLayout.addComponents(saveDistributionBtn, discardDistributionBtn);
buttonsLayout.setComponentAlignment(saveDistributionBtn, Alignment.BOTTOM_LEFT);
buttonsLayout.setComponentAlignment(discardDistributionBtn, Alignment.BOTTOM_RIGHT);
buttonsLayout.addStyleName("window-style");
/*
@@ -186,14 +186,14 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
reqMigStepCheckbox.setId(SPUIComponetIdProvider.DIST_ADD_MIGRATION_CHECK);
/* save or update button */
saveDistribution = SPUIComponentProvider.getButton(SPUIComponetIdProvider.DIST_ADD_SAVE, "", "", "", true,
saveDistributionBtn = SPUIComponentProvider.getButton(SPUIComponetIdProvider.DIST_ADD_SAVE, "", "", "", true,
FontAwesome.SAVE, SPUIButtonStyleSmallNoBorder.class);
saveDistribution.addClickListener(event -> saveDistribution());
saveDistributionBtn.addClickListener(event -> saveDistribution());
/* close button */
discardDistribution = SPUIComponentProvider.getButton(SPUIComponetIdProvider.DIST_ADD_DISCARD, "", "", "", true,
FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
discardDistribution.addClickListener(event -> discardDistribution());
discardDistributionBtn = SPUIComponentProvider.getButton(SPUIComponetIdProvider.DIST_ADD_DISCARD, "", "", "",
true, FontAwesome.TIMES, SPUIButtonStyleSmallNoBorder.class);
discardDistributionBtn.addClickListener(event -> discardDistribution());
}
/**
@@ -216,7 +216,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
}
private void enableSaveButton() {
saveDistribution.setEnabled(true);
saveDistributionBtn.setEnabled(true);
}
private DistributionSetType getDefaultDistributionSetType() {
@@ -226,7 +226,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
}
private void disableSaveButton() {
saveDistribution.setEnabled(false);
saveDistributionBtn.setEnabled(false);
}
private void saveDistribution() {
@@ -415,7 +415,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
distsetTypeNameComboBox.removeStyleName(SPUIStyleDefinitions.SP_COMBOFIELD_ERROR);
descTextArea.clear();
reqMigStepCheckbox.clear();
saveDistribution.setEnabled(true);
saveDistributionBtn.setEnabled(true);
removeListeners();
changedComponents.clear();
}
@@ -497,7 +497,7 @@ public class DistributionAddUpdateWindowLayout extends VerticalLayout {
public void populateValuesOfDistribution(final Long editDistId) {
this.editDistId = editDistId;
editDistribution = Boolean.TRUE;
saveDistribution.setEnabled(false);
saveDistributionBtn.setEnabled(false);
final DistributionSet distSet = distributionSetManagement.findDistributionSetByIdWithDetails(editDistId);
if (distSet != null) {
distNameTextField.setValue(distSet.getName());

View File

@@ -107,32 +107,15 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
super.inittialize();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.hawkbit.server.ui.common.confirmwindow.layout.
* AbstractConfirmationWindowLayout# getConfimrationTabs()
*/
@Override
protected Map<String, ConfirmationTab> getConfimrationTabs() {
final Map<String, ConfirmationTab> tabs = new HashMap<String, ConfirmationTab>();
/**
* create tab for deleted distribution.
*/
/* Create tab for SW Module Type delete */
final Map<String, ConfirmationTab> tabs = new HashMap<>();
if (!managementUIState.getDeletedDistributionList().isEmpty()) {
tabs.put(i18n.get("caption.delete.dist.accordion.tab"), createDeletedDistributionTab());
}
/**
* create tab for deleted target.
*/
if (!managementUIState.getDeletedTargetList().isEmpty()) {
tabs.put(i18n.get("caption.delete.target.accordion.tab"), createDeletedTargetTab());
}
/**
* create tab for assignment.
*/
if (!managementUIState.getAssignedList().isEmpty()) {
tabs.put(i18n.get("caption.assign.dist.accordion.tab"), createAssignmentTab());
}
@@ -196,8 +179,8 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
private void saveAllAssignments(final ConfirmationTab tab) {
final Set<TargetIdName> itemIds = managementUIState.getAssignedList().keySet();
Long distId;
List<TargetIdName> targetIdSetList = null;
List<TargetIdName> tempIdList = null;
List<TargetIdName> targetIdSetList;
List<TargetIdName> tempIdList;
final ActionType actionType = ((ActionTypeOptionGroupLayout.ActionTypeOption) actionTypeOptionGroupLayout
.getActionTypeOptionGroup().getValue()).getActionType();
final long forcedTimeStamp = (((ActionTypeOptionGroupLayout.ActionTypeOption) actionTypeOptionGroupLayout
@@ -205,7 +188,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
? actionTypeOptionGroupLayout.getForcedTimeDateField().getValue().getTime()
: Action.NO_FORCE_TIME;
final Map<Long, ArrayList<TargetIdName>> saveAssignedList = new HashMap<Long, ArrayList<TargetIdName>>();
final Map<Long, ArrayList<TargetIdName>> saveAssignedList = new HashMap<>();
int successAssignmentCount = 0;
int duplicateAssignmentCount = 0;
@@ -216,7 +199,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
if (saveAssignedList.containsKey(distId)) {
targetIdSetList = saveAssignedList.get(distId);
} else {
targetIdSetList = new ArrayList<TargetIdName>();
targetIdSetList = new ArrayList<>();
}
targetIdSetList.add(itemId);
saveAssignedList.put(distId, (ArrayList<TargetIdName>) targetIdSetList);
@@ -275,15 +258,13 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
}
private String getAssigmentSuccessMessage(final int assignedCount) {
final String assignment = FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
return FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
+ i18n.get("message.target.assignment", new Object[] { assignedCount });
return assignment;
}
private String getDuplicateAssignmentMessage(final int alreadyAssignedCount) {
final String alreadyAssigned = FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
return FontAwesome.TASKS.getHtml() + SPUILabelDefinitions.HTML_SPACE
+ i18n.get("message.target.alreadyAssigned", new Object[] { alreadyAssignedCount });
return alreadyAssigned;
}
private void discardAllAssignments(final ConfirmationTab tab) {
@@ -456,7 +437,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
}
private void deleteAllDistributions(final ConfirmationTab tab) {
final Set<Long> deletedIds = new HashSet<Long>();
final Set<Long> deletedIds = new HashSet<>();
managementUIState.getDeletedDistributionList().forEach(distIdName -> deletedIds.add(distIdName.getId()));
distributionSetManagement.deleteDistributionSet(deletedIds.toArray(new Long[deletedIds.size()]));
addToConsolitatedMsg(FontAwesome.TRASH_O.getHtml() + SPUILabelDefinitions.HTML_SPACE
@@ -516,7 +497,7 @@ public class ManangementConfirmationWindowLayout extends AbstractConfirmationWin
final IndexedContainer contactContainer = new IndexedContainer();
contactContainer.addContainerProperty(TARGET_ID, String.class, "");
contactContainer.addContainerProperty(TARGET_NAME, String.class, "");
Item item = null;
Item item;
for (final TargetIdName targteId : managementUIState.getDeletedTargetList()) {
item = contactContainer.addItem(targteId);
item.getItemProperty(TARGET_ID).setValue(targteId.getControllerId());

View File

@@ -62,20 +62,20 @@ public class ManagementUIState implements Serializable {
private boolean distTagFilterClosed = true;
private Long targetsTruncated = null;
private Long targetsTruncated;
private final AtomicLong targetsCountAll = new AtomicLong();
private boolean isDsTableMaximized = Boolean.FALSE;
private boolean dsTableMaximized = Boolean.FALSE;
// Contains ID and NAme of last selected target
private DistributionSetIdName lastSelectedDsIdName;
// Contains list of ID and Names of all the selected Targets
private Set<DistributionSetIdName> selectedDsIdName = Collections.emptySet();
private boolean isTargetTableMaximized = Boolean.FALSE;
private boolean targetTableMaximized = Boolean.FALSE;
private boolean isActionHistoryMaximized = Boolean.FALSE;
private boolean actionHistoryMaximized = Boolean.FALSE;
private boolean noDataAvilableTarget = Boolean.FALSE;
@@ -255,11 +255,11 @@ public class ManagementUIState implements Serializable {
}
public boolean isDsTableMaximized() {
return isDsTableMaximized;
return dsTableMaximized;
}
public void setDsTableMaximized(final boolean isDsTableMaximized) {
this.isDsTableMaximized = isDsTableMaximized;
this.dsTableMaximized = isDsTableMaximized;
}
public DistributionSetIdName getLastSelectedDsIdName() {
@@ -282,7 +282,7 @@ public class ManagementUIState implements Serializable {
* @return the isTargetTableMaximized
*/
public boolean isTargetTableMaximized() {
return isTargetTableMaximized;
return targetTableMaximized;
}
/**
@@ -290,14 +290,14 @@ public class ManagementUIState implements Serializable {
* the isTargetTableMaximized to set
*/
public void setTargetTableMaximized(final boolean isTargetTableMaximized) {
this.isTargetTableMaximized = isTargetTableMaximized;
this.targetTableMaximized = isTargetTableMaximized;
}
/**
* @return the isActionHistoryMaximized
*/
public boolean isActionHistoryMaximized() {
return isActionHistoryMaximized;
return actionHistoryMaximized;
}
/**
@@ -305,7 +305,7 @@ public class ManagementUIState implements Serializable {
* the isActionHistoryMaximized to set
*/
public void setActionHistoryMaximized(final boolean isActionHistoryMaximized) {
this.isActionHistoryMaximized = isActionHistoryMaximized;
this.actionHistoryMaximized = isActionHistoryMaximized;
}
/**

View File

@@ -18,17 +18,16 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.HawkbitServerProperties;
import org.eclipse.hawkbit.im.authentication.PermissionService;
import org.eclipse.hawkbit.im.authentication.UserPrincipal;
import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.documentation.DocumentationPageLink;
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
import org.eclipse.hawkbit.util.SPInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
@@ -42,7 +41,6 @@ import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
@@ -50,7 +48,6 @@ import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
import com.vaadin.ui.MenuBar;
import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
@@ -61,11 +58,17 @@ import com.vaadin.ui.themes.ValoTheme;
*/
@SpringComponent
@UIScope
public final class DashboardMenu extends CustomComponent implements EnvironmentAware {
public final class DashboardMenu extends CustomComponent {
@Autowired
private I18N i18n;
@Autowired
private transient UiProperties uiProperties;
@Autowired
private transient HawkbitServerProperties serverProperties;
private static final long serialVersionUID = 5394474618559481462L;
public static final String ID = "dashboard-menu";
@@ -74,16 +77,12 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
private static final String STYLE_VISIBLE = "valo-menu-visible";
// this should be resolved when we introduce event bus on UI to just inform
// the buttons directly
// via events
// the buttons directly via events
private final List<ValoMenuItemButton> menuButtons = new ArrayList<>();
@Autowired
private transient PermissionService permissionService;
@Autowired
private transient SPInfo spInfo;
@Autowired
private final List<DashboardMenuItem> dashboardVaadinViews = new ArrayList<>();
@@ -91,12 +90,10 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
private boolean accessibleViewsEmpty;
private String userManagementLoginUrl;
/**
* initializing the view and creating the layout, cannot be done in the
* custructor because the constructor will be called by spring and the
* dashabord must be initialized when the dashboard UI is creating.
* constructor because the constructor will be called by spring and the
* dashboard must be initialized when the dashboard UI is creating.
*/
public void init() {
initialViewName = "";
@@ -162,20 +159,20 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
links.addComponent(docuLink);
links.setComponentAlignment(docuLink, Alignment.BOTTOM_CENTER);
if (userManagementLoginUrl != null) {
if (!uiProperties.getLinks().getUserManagement().isEmpty()) {
final Link userManagementLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_USERMANAGEMENT,
i18n.get("link.usermanagement.name"), userManagementLoginUrl, FontAwesome.USERS, "_blank",
linkStyle, true);
i18n.get("link.usermanagement.name"), uiProperties.getLinks().getUserManagement(),
FontAwesome.USERS, "_blank", linkStyle, true);
userManagementLink.setDescription(i18n.get("link.usermanagement.name"));
links.addComponent(userManagementLink);
userManagementLink.setSizeFull();
links.setComponentAlignment(userManagementLink, Alignment.BOTTOM_CENTER);
}
if (spInfo.getSupportEmail() != null) {
if (!uiProperties.getLinks().getSupport().isEmpty()) {
final Link supportLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_SUPPORT,
i18n.get("link.support.name"), spInfo.getSupportEmail(), FontAwesome.ENVELOPE_O, "", linkStyle,
true);
i18n.get("link.support.name"), uiProperties.getLinks().getSupport(), FontAwesome.ENVELOPE_O, "",
linkStyle, true);
supportLink.setDescription(i18n.get("link.support.name"));
supportLink.setSizeFull();
links.addComponent(supportLink);
@@ -222,12 +219,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
settingsItem.setDescription(user.getUsername());
}
settingsItem.addItem("Sign Out", new Command() {
@Override
public void menuSelected(final MenuItem selectedItem) {
Page.getCurrent().setLocation("/UI/logout");
}
});
settingsItem.addItem("Sign Out", selectedItem -> Page.getCurrent().setLocation("/UI/logout"));
return settings;
}
@@ -254,14 +246,11 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
}
private Component buildToggleButton() {
final Button valoMenuToggleButton = new Button("Menu", new ClickListener() {
@Override
public void buttonClick(final ClickEvent event) {
if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) {
getCompositionRoot().removeStyleName(STYLE_VISIBLE);
} else {
getCompositionRoot().addStyleName(STYLE_VISIBLE);
}
final Button valoMenuToggleButton = new Button("Menu", (ClickListener) event -> {
if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) {
getCompositionRoot().removeStyleName(STYLE_VISIBLE);
} else {
getCompositionRoot().addStyleName(STYLE_VISIBLE);
}
});
valoMenuToggleButton.setIcon(FontAwesome.LIST);
@@ -307,7 +296,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
final Label label = new Label();
label.setSizeFull();
label.setStyleName("version-layout");
label.setValue(spInfo.getVersion());
label.setValue(serverProperties.getBuild().getVersion());
return label;
}
@@ -341,11 +330,6 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
menuButtons.forEach(button -> button.postViewChange(event));
}
@Override
public void setEnvironment(final Environment environment) {
userManagementLoginUrl = environment.getProperty("hawkbit.server.im.login.url", String.class);
}
/**
* Returns the dashboard view type by a given view name.
*
@@ -411,12 +395,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
setDescription(view.getDashboardCaptionLong());
/* Avoid double click */
setDisableOnClick(true);
addClickListener(new ClickListener() {
@Override
public void buttonClick(final ClickEvent event) {
event.getComponent().getUI().getNavigator().navigateTo(view.getViewName());
}
});
addClickListener(event -> event.getComponent().getUI().getNavigator().navigateTo(view.getViewName()));
}

View File

@@ -0,0 +1,244 @@
/**
* 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.push;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.eventbus.event.DistributionSetTagCreatedBulkEvent;
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
import org.eclipse.hawkbit.eventbus.event.RolloutChangeEvent;
import org.eclipse.hawkbit.eventbus.event.RolloutGroupChangeEvent;
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.eventbus.event.TargetTagCreatedBulkEvent;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventBus.SessionEventBus;
import com.google.common.collect.Sets;
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import com.vaadin.server.VaadinSession;
import com.vaadin.server.VaadinSession.State;
import com.vaadin.server.WrappedSession;
import com.vaadin.ui.UI;
/**
* A {@link EventPushStrategy} implementation which retrieves events from
* {@link com.google.common.eventbus.EventBus} and store them first in an queue
* where they will dispatched every 2 seconds to the {@link EventBus} in a
* Vaadin access thread {@link UI#access(Runnable)}.
*
* This strategy avoids blocking UIs when too many events are fired and
* dispatched to the UI thread. The UI will freeze in the time. To avoid that
* all events are collected first and same events are merged to a list of events
* before they dispatched to the UI thread.
*
* The strategy also verifies the current tenant in the session with the tenant
* in the event and only forwards event from the right tenant to the UI.
*
*/
public class DelayedEventBusPushStrategy implements EventPushStrategy {
private static final Logger LOG = LoggerFactory.getLogger(DelayedEventBusPushStrategy.class);
private static final int BLOCK_SIZE = 10_000;
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
private final BlockingDeque<org.eclipse.hawkbit.eventbus.event.Event> queue = new LinkedBlockingDeque<>(BLOCK_SIZE);
private final EventBus.SessionEventBus eventBus;
private final com.google.common.eventbus.EventBus systemEventBus;
private ScheduledFuture<?> jobHandle;
/**
* only events defined in the set are dispatched to the session event bus.
*/
private static final Set<Class<?>> UI_EVENTS = Sets.newHashSet(TargetInfoUpdateEvent.class,
TargetCreatedEvent.class, TargetDeletedEvent.class, RolloutChangeEvent.class, RolloutGroupChangeEvent.class,
TargetTagCreatedBulkEvent.class, DistributionSetTagCreatedBulkEvent.class);
/**
* Constructor.
*
* @param eventBus
* the session event bus to where the events should be dispatched
* @param systemEventBus
* the system event bus where to retrieve the events from the
* back-end
*/
public DelayedEventBusPushStrategy(final SessionEventBus eventBus,
final com.google.common.eventbus.EventBus systemEventBus) {
this.eventBus = eventBus;
this.systemEventBus = systemEventBus;
}
/**
* An {@link com.google.common.eventbus.EventBus} subscriber which
* subscribes {@link EntityEvent} from the repository to dispatch these
* events to the UI {@link SessionEventBus}.
*
* @param event
* the entity event which has been published from the repository
*/
@Subscribe
@AllowConcurrentEvents
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
// to dispatch too many events which are not interested on the UI
if (UI_EVENTS.contains(event.getClass()) && !queue.offer(event)) {
LOG.warn("Deque limit is reached, cannot add more events!!! Dropped event is {}", event);
return;
}
}
@Override
public void init(final UI vaadinUI) {
LOG.debug("Initialize delayed event push strategy");
jobHandle = executorService.scheduleWithFixedDelay(new DispatchRunnable(vaadinUI, vaadinUI.getSession()), 500,
2000, TimeUnit.MILLISECONDS);
systemEventBus.register(this);
}
@Override
public void clean() {
LOG.debug("Cleanup resources");
jobHandle.cancel(true);
systemEventBus.unregister(this);
executorService.shutdownNow();
queue.clear();
}
/**
* Checks if the tenant within the event is equal with the current tenant in
* the context.
*
* @param userContext
* the security context of the current session
* @param event
* the event to dispatch to the UI
* @return {@code true} if the event can be dispatched to the UI otherwise
* {@code false}
*/
protected boolean eventSecurityCheck(final SecurityContext userContext,
final org.eclipse.hawkbit.eventbus.event.Event event) {
if (userContext == null || userContext.getAuthentication() == null) {
return false;
}
final Object tenantAuthenticationDetails = userContext.getAuthentication().getDetails();
if (tenantAuthenticationDetails instanceof TenantAwareAuthenticationDetails) {
return ((TenantAwareAuthenticationDetails) tenantAuthenticationDetails).getTenant()
.equalsIgnoreCase(event.getTenant());
}
return false;
}
private final class DispatchRunnable implements Runnable {
private final UI vaadinUI;
private final VaadinSession vaadinSession;
private DispatchRunnable(final UI ui, final VaadinSession session) {
vaadinUI = ui;
vaadinSession = session;
}
@Override
public void run() {
LOG.debug("UI EventBus aggregator started");
final long timestamp = System.currentTimeMillis();
final List<org.eclipse.hawkbit.eventbus.event.Event> events = new LinkedList<>();
for (int i = 0; i < BLOCK_SIZE; i++) {
final org.eclipse.hawkbit.eventbus.event.Event pollEvent = queue.poll();
if (pollEvent == null) {
continue;
}
events.add(pollEvent);
}
if (events.isEmpty()) {
return;
}
if (vaadinSession == null) {
return;
}
LOG.debug("UI EventBus aggregator session: {}", vaadinSession);
final WrappedSession wrappedSession = vaadinSession.getSession();
if (wrappedSession == null) {
return;
}
final int eventsSize = events.size();
doDispatch(events, wrappedSession);
LOG.debug("UI EventBus aggregator done with sending {} events in {} ms", eventsSize,
System.currentTimeMillis() - timestamp);
}
private void doDispatch(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
final WrappedSession wrappedSession) {
final SecurityContext userContext = (SecurityContext) wrappedSession
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
final SecurityContext oldContext = SecurityContextHolder.getContext();
try {
SecurityContextHolder.setContext(userContext);
vaadinUI.access(() -> {
if (vaadinSession.getState() != State.OPEN) {
return;
}
fowardEvents(events, userContext);
// send a list of events, because ui performance issues
publishEventAsList(events, userContext, TargetInfoUpdateEvent.class);
publishEventAsList(events, userContext, TargetCreatedEvent.class);
publishEventAsList(events, userContext, TargetDeletedEvent.class);
});
} finally {
SecurityContextHolder.setContext(oldContext);
}
}
private void publishEventAsList(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
final SecurityContext userContext, final Class<?> eventType) {
final List<org.eclipse.hawkbit.eventbus.event.Event> bulkEvents = events.stream()
.filter(event -> DelayedEventBusPushStrategy.this.eventSecurityCheck(userContext, event)
&& eventType.isInstance(event))
.collect(Collectors.toList());
if (bulkEvents.isEmpty()) {
return;
}
eventBus.publish(vaadinUI, bulkEvents);
}
private void fowardEvents(final List<org.eclipse.hawkbit.eventbus.event.Event> events,
final SecurityContext userContext) {
events.stream().filter(event -> DelayedEventBusPushStrategy.this.eventSecurityCheck(userContext, event))
.forEach(event -> eventBus.publish(vaadinUI, event));
}
}
}

View File

@@ -0,0 +1,33 @@
/**
* 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.push;
import com.vaadin.ui.UI;
/**
* Interface declaring a strategy to push events from the back-end to the UI.
*
*/
public interface EventPushStrategy {
/**
* Initialize the event push strategy, this is bound to the life-cycle of
* the {@link UI} so the strategy can be initialized based a {@link UI}.
*
* @param vaadinUI
* the {@link UI}
*/
void init(UI vaadinUI);
/**
* Cleans up resources when the strategy is not be used anymore e.g.
* {@link UI#detach()}.
*/
void clean();
}

View File

@@ -128,9 +128,9 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private TextArea description;
private Button saveRollout;
private Button saveRolloutBtn;
private Button discardRolllout;
private Button discardRollloutBtn;
private OptionGroup errorThresholdOptionGroup;
@@ -138,7 +138,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private Window addUpdateRolloutWindow;
private Boolean editRollout;
private Boolean editRolloutEnabled;
private Rollout rolloutForEdit;
@@ -167,7 +167,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
* Reset the field values.
*/
public void resetComponents() {
editRollout = Boolean.FALSE;
editRolloutEnabled = Boolean.FALSE;
rolloutName.clear();
targetFilterQuery.clear();
resetFields();
@@ -212,7 +212,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
final HorizontalLayout groupLayout = new HorizontalLayout();
groupLayout.setSizeFull();
groupLayout.addComponents(noOfGroups, groupSizeLabel);
groupLayout.setExpandRatio(noOfGroups, 1.0f);
groupLayout.setExpandRatio(noOfGroups, 1.0F);
groupLayout.setComponentAlignment(groupSizeLabel, Alignment.MIDDLE_LEFT);
return groupLayout;
}
@@ -221,7 +221,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
final HorizontalLayout errorThresoldLayout = new HorizontalLayout();
errorThresoldLayout.setSizeFull();
errorThresoldLayout.addComponents(errorThreshold, errorThresholdOptionGroup);
errorThresoldLayout.setExpandRatio(errorThreshold, 1.0f);
errorThresoldLayout.setExpandRatio(errorThreshold, 1.0F);
return errorThresoldLayout;
}
@@ -229,9 +229,9 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
final HorizontalLayout targetFilterLayout = new HorizontalLayout();
targetFilterLayout.setSizeFull();
targetFilterLayout.addComponents(targetFilterQueryCombo, targetFilterQuery, totalTargetsLabel);
targetFilterLayout.setExpandRatio(targetFilterQueryCombo, 0.71f);
targetFilterLayout.setExpandRatio(targetFilterQuery, 0.70f);
targetFilterLayout.setExpandRatio(totalTargetsLabel, 0.29f);
targetFilterLayout.setExpandRatio(targetFilterQueryCombo, 0.71F);
targetFilterLayout.setExpandRatio(targetFilterQuery, 0.70F);
targetFilterLayout.setExpandRatio(totalTargetsLabel, 0.29F);
targetFilterLayout.setComponentAlignment(totalTargetsLabel, Alignment.MIDDLE_LEFT);
return targetFilterLayout;
}
@@ -240,7 +240,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
final HorizontalLayout triggerThresholdLayout = new HorizontalLayout();
triggerThresholdLayout.setSizeFull();
triggerThresholdLayout.addComponents(triggerThreshold, getPercentHintLabel());
triggerThresholdLayout.setExpandRatio(triggerThreshold, 1.0f);
triggerThresholdLayout.setExpandRatio(triggerThreshold, 1.0F);
return triggerThresholdLayout;
}
@@ -254,9 +254,9 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private HorizontalLayout getSaveDiscardButtonLayout() {
final HorizontalLayout buttonsLayout = new HorizontalLayout();
buttonsLayout.setSizeFull();
buttonsLayout.addComponents(saveRollout, discardRolllout);
buttonsLayout.setComponentAlignment(saveRollout, Alignment.BOTTOM_LEFT);
buttonsLayout.setComponentAlignment(discardRolllout, Alignment.BOTTOM_RIGHT);
buttonsLayout.addComponents(saveRolloutBtn, discardRollloutBtn);
buttonsLayout.setComponentAlignment(saveRolloutBtn, Alignment.BOTTOM_LEFT);
buttonsLayout.setComponentAlignment(discardRollloutBtn, Alignment.BOTTOM_RIGHT);
buttonsLayout.addStyleName("window-style");
return buttonsLayout;
}
@@ -277,8 +277,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
description = createDescription();
errorThresholdOptionGroup = createErrorThresholdOptionGroup();
setDefaultSaveStartGroupOption();
saveRollout = createSaveButton();
discardRolllout = createDiscardButton();
saveRolloutBtn = createSaveButton();
discardRollloutBtn = createDiscardButton();
actionTypeOptionGroupLayout.selectDefaultOption();
totalTargetsLabel = createTotalTargetsLabel();
@@ -383,8 +383,9 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private Container createTargetFilterComboContainer() {
final BeanQueryFactory<TargetFilterBeanQuery> targetFilterQF = new BeanQueryFactory<>(
TargetFilterBeanQuery.class);
return new LazyQueryContainer(new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE,
SPUILabelDefinitions.VAR_NAME), targetFilterQF);
return new LazyQueryContainer(
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_NAME),
targetFilterQF);
}
@@ -410,7 +411,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
}
private void onRolloutSave() {
if (editRollout) {
if (editRolloutEnabled) {
editRollout();
} else {
createRollout();
@@ -422,8 +423,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
rolloutForEdit.setName(rolloutName.getValue());
rolloutForEdit.setDescription(description.getValue());
final DistributionSetIdName distributionSetIdName = (DistributionSetIdName) distributionSet.getValue();
rolloutForEdit.setDistributionSet(distributionSetManagement.findDistributionSetById(distributionSetIdName
.getId()));
rolloutForEdit.setDistributionSet(
distributionSetManagement.findDistributionSetById(distributionSetIdName.getId()));
rolloutForEdit.setActionType(getActionType());
rolloutForEdit.setForcedTime(getForcedTimeStamp());
final int amountGroup = Integer.parseInt(noOfGroups.getValue());
@@ -453,8 +454,9 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private long getForcedTimeStamp() {
return (((ActionTypeOptionGroupLayout.ActionTypeOption) actionTypeOptionGroupLayout.getActionTypeOptionGroup()
.getValue()) == ActionTypeOption.AUTO_FORCED) ? actionTypeOptionGroupLayout.getForcedTimeDateField()
.getValue().getTime() : Action.NO_FORCE_TIME;
.getValue()) == ActionTypeOption.AUTO_FORCED)
? actionTypeOptionGroupLayout.getForcedTimeDateField().getValue().getTime()
: Action.NO_FORCE_TIME;
}
private ActionType getActionType() {
@@ -487,8 +489,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
rolloutToCreate.setName(rolloutName.getValue());
rolloutToCreate.setDescription(description.getValue());
rolloutToCreate.setTargetFilterQuery(targetFilter);
rolloutToCreate.setDistributionSet(distributionSetManagement.findDistributionSetById(distributionSetIdName
.getId()));
rolloutToCreate
.setDistributionSet(distributionSetManagement.findDistributionSetById(distributionSetIdName.getId()));
rolloutToCreate.setActionType(getActionType());
rolloutToCreate.setForcedTime(getForcedTimeStamp());
@@ -499,8 +501,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private String getTargetFilterQuery() {
if (null != targetFilterQueryCombo.getValue()
&& HawkbitCommonUtil.trimAndNullIfEmpty((String) targetFilterQueryCombo.getValue()) != null) {
final Item filterItem = targetFilterQueryCombo.getContainerDataSource().getItem(
targetFilterQueryCombo.getValue());
final Item filterItem = targetFilterQueryCombo.getContainerDataSource()
.getItem(targetFilterQueryCombo.getValue());
return (String) filterItem.getItemProperty("query").getValue();
}
return null;
@@ -568,8 +570,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private boolean duplicateCheck() {
if (rolloutManagement.findRolloutByName(getRolloutName()) != null) {
uiNotification.displayValidationError(i18n.get("message.rollout.duplicate.check",
new Object[] { getRolloutName() }));
uiNotification.displayValidationError(
i18n.get("message.rollout.duplicate.check", new Object[] { getRolloutName() }));
return false;
}
return true;
@@ -580,9 +582,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
}
private TextArea createDescription() {
final TextArea descriptionField = SPUIComponentProvider.getTextArea("text-area-style",
ValoTheme.TEXTFIELD_TINY, false, null, i18n.get("textfield.description"),
SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
final TextArea descriptionField = SPUIComponentProvider.getTextArea("text-area-style", ValoTheme.TEXTFIELD_TINY,
false, null, i18n.get("textfield.description"), SPUILabelDefinitions.TEXT_AREA_MAX_LENGTH);
descriptionField.setId(SPUIComponetIdProvider.ROLLOUT_DESCRIPTION_ID);
descriptionField.setNullRepresentation(HawkbitCommonUtil.SP_STRING_EMPTY);
descriptionField.setSizeFull();
@@ -647,8 +648,9 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
private Container createDsComboContainer() {
final BeanQueryFactory<DistBeanQuery> distributionQF = new BeanQueryFactory<>(DistBeanQuery.class);
return new LazyQueryContainer(new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE,
SPUILabelDefinitions.VAR_DIST_ID_NAME), distributionQF);
return new LazyQueryContainer(
new LazyQueryDefinition(true, SPUIDefinitions.PAGE_SIZE, SPUILabelDefinitions.VAR_DIST_ID_NAME),
distributionQF);
}
@@ -682,8 +684,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
try {
if (HawkbitCommonUtil.trimAndNullIfEmpty(noOfGroups.getValue()) == null
|| HawkbitCommonUtil.trimAndNullIfEmpty((String) targetFilterQueryCombo.getValue()) == null) {
uiNotification.displayValidationError(i18n
.get("message.rollout.noofgroups.or.targetfilter.missing"));
uiNotification
.displayValidationError(i18n.get("message.rollout.noofgroups.or.targetfilter.missing"));
} else {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value);
final int groupSize = getGroupSize();
@@ -708,8 +710,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
public void validate(final Object value) {
try {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value);
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100).validate(Integer
.valueOf(value.toString()));
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 100), 0, 100)
.validate(Integer.valueOf(value.toString()));
} catch (final InvalidValueException ex) {
throw ex;
}
@@ -723,8 +725,8 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
public void validate(final Object value) {
try {
new RegexpValidator(NUMBER_REGEXP, i18n.get(MESSAGE_ENTER_NUMBER)).validate(value);
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500).validate(Integer
.valueOf(value.toString()));
new IntegerRangeValidator(i18n.get(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, 500), 0, 500)
.validate(Integer.valueOf(value.toString()));
} catch (final InvalidValueException ex) {
throw ex;
}
@@ -740,7 +742,7 @@ public class AddUpdateRolloutWindowLayout extends CustomComponent {
*/
public void populateData(final Long rolloutId) {
resetComponents();
editRollout = Boolean.TRUE;
editRolloutEnabled = Boolean.TRUE;
rolloutForEdit = rolloutManagement.findRolloutById(rolloutId);
rolloutName.setValue(rolloutForEdit.getName());
description.setValue(rolloutForEdit.getDescription());

View File

@@ -83,10 +83,9 @@ public class GatewaySecurityTokenAuthenticationConfigurationItem extends Abstrac
gatewayTokenNameTextField = SPUIComponentProvider.getTextField("", ValoTheme.TEXTFIELD_TINY, false, null, "",
true, SPUILabelDefinitions.TEXT_FIELD_MAX_LENGTH);
gatewayTokenNameTextField.setImmediate(true);
// hide text field until we support multiple gateway tokens for a tenant
// MECS-830
// hide text field until we support multiple gateway tokens for a tenan
gatewayTokenNameTextField.setVisible(false);
gatewayTokenNameTextField.addTextChangeListener(event -> keyNameChanged());
gatewayTokenNameTextField.addTextChangeListener(event -> doKeyNameChanged());
final Button gatewaytokenBtn = SPUIComponentProvider.getButton("TODO-ID", "Regenerate Key", "",
ValoTheme.BUTTON_TINY + " " + "redicon", true, null, SPUIButtonStyleSmall.class);
@@ -116,10 +115,7 @@ public class GatewaySecurityTokenAuthenticationConfigurationItem extends Abstrac
}
}
/**
* @return
*/
private void keyNameChanged() {
private void doKeyNameChanged() {
keyNameChanged = true;
notifyConfigurationChanged();
}

View File

@@ -25,7 +25,13 @@ import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@Features("Unit Tests - Management UI")
@Stories("Push Security")
@RunWith(MockitoJUnitRunner.class)
// TODO: create description annotations
public class SpringSecurityAtmosphereInterceptorTest {
@Mock

View File

@@ -24,7 +24,7 @@ import org.springframework.context.annotation.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@Features("Component Tests - UI")
@Features("Unit Tests - Management UI")
@Stories("Threads with NamingThreadFactory")
@RunWith(MockitoJUnitRunner.class)
public class NamingThreadFactoryTest {

View File

@@ -19,12 +19,15 @@ import com.vaadin.shared.ui.label.ContentMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
/**
* Unit Test block for UI Component provider. Dynamic Factory Testing.
*
*
*
*/
@Features("Unit Tests - Management UI")
@Stories("UI components")
public class SPUIComponentProviderTest {
/**
* Test case for check button factory.