Synchronization of UserContainer with UserService
The UserContainer class is now instantiated by OSGI.
It is notified via the event service each time a
user is added/modified within the current UserService
implementation.
Change-Id: I51811bf359abc6f477afe78190cdb24145ae1b19
Signed-off-by: Frederic SIVIGNON <frederic.sivignon@sap.com>
Signed-off-by: Michael Ochmann <michael.ochmann@sap.com>
diff --git a/org.eclipse.skalli.api/src/main/java/org/eclipse/skalli/services/user/EventUserUpdate.java b/org.eclipse.skalli.api/src/main/java/org/eclipse/skalli/services/user/EventUserUpdate.java
new file mode 100644
index 0000000..69d4d37
--- /dev/null
+++ b/org.eclipse.skalli.api/src/main/java/org/eclipse/skalli/services/user/EventUserUpdate.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017 SAP AG 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
+ *
+ * Contributors:
+ * SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.skalli.services.user;
+
+import org.eclipse.skalli.model.User;
+import org.eclipse.skalli.services.event.Event;
+import org.eclipse.skalli.services.event.EventService;
+
+/**
+ * Event that notifies about changes to the user base cache. This event is fired by
+ * the {@link EventService} when a user is added or updated in the current UserService
+ * instance.
+ * <br>
+ * Any service that for example caches or shows {@link org.eclipse.skalli.model.User users}
+ * should register to this event
+ * (see {@link org.eclipse.skalli.services.event.EventService#registerListener(Class,
+ * org.eclipse.skalli.services.event.EventListener)}).
+ */
+public class EventUserUpdate extends Event {
+
+ private final User user;
+
+ /**
+ * Creates a user update event.
+ *
+ * @param user the user that has been updated
+ */
+ public EventUserUpdate(User user) {
+ this.user = user;
+ }
+
+ /**
+ * Returns the user that has been updated.
+ */
+ public User getUser() {
+ return user;
+ }
+}
diff --git a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/LocalUserComponent.java b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/LocalUserComponent.java
index 4e2a0d3..1f8da28 100644
--- a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/LocalUserComponent.java
+++ b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/LocalUserComponent.java
@@ -28,7 +28,9 @@
import org.eclipse.skalli.model.User;
import org.eclipse.skalli.model.ValidationException;
import org.eclipse.skalli.services.entity.EntityServiceBase;
+import org.eclipse.skalli.services.event.EventService;
import org.eclipse.skalli.services.extension.DataMigration;
+import org.eclipse.skalli.services.user.EventUserUpdate;
import org.eclipse.skalli.services.user.UserService;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentContext;
@@ -50,6 +52,7 @@
private static final Logger LOG = LoggerFactory.getLogger(LocalUserComponent.class);
private static final int CURRENT_MODEL_VERISON = 20;
+ private EventService eventService;
private Map<String, User> cache;
@@ -64,6 +67,11 @@
}
@Override
+ protected void bindEventService(EventService eventService) {
+ this.eventService = eventService;
+ }
+
+ @Override
public Class<User> getEntityClass() {
return User.class;
}
@@ -92,6 +100,10 @@
cache = new HashMap<String, User>();
for (User user: getAll()) {
cache.put(user.getUserId(), user);
+
+ if (this.eventService != null) {
+ this.eventService.fireEvent(new EventUserUpdate(user));
+ }
}
}
return cache;
diff --git a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java
index a216f6c..2784a24 100644
--- a/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java
+++ b/org.eclipse.skalli.core/src/main/java/org/eclipse/skalli/core/user/ldap/LDAPUserComponent.java
@@ -41,6 +41,7 @@
import org.eclipse.skalli.services.configuration.EventConfigUpdate;
import org.eclipse.skalli.services.event.EventListener;
import org.eclipse.skalli.services.event.EventService;
+import org.eclipse.skalli.services.user.EventUserUpdate;
import org.eclipse.skalli.services.user.UserService;
import org.eclipse.skalli.services.user.ldap.LdapContextProvider;
import org.osgi.service.component.ComponentConstants;
@@ -72,6 +73,7 @@
private String destination;
private String baseDN;
private String searchScope;
+ private EventService eventService;
private Cache<String, User> cache;
@@ -98,10 +100,12 @@
protected void bindEventService(EventService eventService) {
eventService.registerListener(EventConfigUpdate.class, this);
+ this.eventService = eventService;
}
protected void unbindEventService(EventService eventService) {
eventService.unregisterListener(EventConfigUpdate.class, this);
+ this.eventService = null;
}
protected void bindConfigurationService(ConfigurationService configurationService) {
@@ -152,12 +156,26 @@
List<User> users = searchUserByName(searchText);
for (User user : users) {
if (user != null) {
- cache.put(StringUtils.lowerCase(user.getUserId()), user);
+ addUserToCache(user);
}
}
return users;
}
+ /**
+ * Adds or updates the given user within the cache class data member.
+ * Also fires an event so other user cache instances can be updated (See UserContainer class).
+ * @param user
+ */
+ private void addUserToCache(User user){
+ cache.put(user.getUserId().toLowerCase(Locale.ENGLISH), user);
+
+ if (this.eventService != null) {
+ this.eventService.fireEvent(new EventUserUpdate(user));
+ }
+ }
+
+
@Override
public synchronized User getUserById(String userId) {
if (StringUtils.isBlank(userId)) {
@@ -171,7 +189,7 @@
}
user = searchUserById(userId);
if (user != null) {
- cache.put(lowerCaseUserId, user);
+ addUserToCache(user);
}
}
return user;
@@ -210,8 +228,8 @@
if (user != null) {
String userId = user.getUserId();
if (StringUtils.isNotBlank(userId)) {
- cache.put(userId.toLowerCase(Locale.ENGLISH), user);
users.add(user);
+ addUserToCache(user);
}
}
}
diff --git a/org.eclipse.skalli.view/META-INF/MANIFEST.MF b/org.eclipse.skalli.view/META-INF/MANIFEST.MF
index 98331ce..f3c6dec 100644
--- a/org.eclipse.skalli.view/META-INF/MANIFEST.MF
+++ b/org.eclipse.skalli.view/META-INF/MANIFEST.MF
@@ -31,6 +31,7 @@
org.eclipse.skalli.services,
org.eclipse.skalli.services.configuration,
org.eclipse.skalli.services.entity,
+ org.eclipse.skalli.services.event,
org.eclipse.skalli.services.extension,
org.eclipse.skalli.services.extension.rest,
org.eclipse.skalli.services.favorites,
@@ -57,7 +58,8 @@
OSGI-INF/TopLinksConfigSection.xml,
OSGI-INF/NewsConfigSection.xml,
OSGI-INF/UserDetailsConfigSection.xml,
- OSGI-INF/BrandingConfigSection.xml
+ OSGI-INF/BrandingConfigSection.xml,
+ OSGI-INF/UserContainer.xml
Web-ContextPath: /
Webapp-Context: /
Export-Package: org.eclipse.skalli.view,
diff --git a/org.eclipse.skalli.view/OSGI-INF/UserContainer.xml b/org.eclipse.skalli.view/OSGI-INF/UserContainer.xml
new file mode 100644
index 0000000..beffbb0
--- /dev/null
+++ b/org.eclipse.skalli.view/OSGI-INF/UserContainer.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2010-2017 SAP AG 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
+
+ Contributors:
+ SAP AG - initial API and implementation
+ -->
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.skalli.view.internal.container.UserContainer">
+ <implementation class="org.eclipse.skalli.view.internal.container.UserContainer"/>
+ <reference
+ name="EventService"
+ interface="org.eclipse.skalli.services.event.EventService"
+ cardinality="0..1"
+ policy="dynamic"
+ bind="bindEventService"
+ unbind="unbindEventService" />
+</scr:component>
diff --git a/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/component/UserSelectCombo.java b/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/component/UserSelectCombo.java
index d20274e..1ddb96b 100644
--- a/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/component/UserSelectCombo.java
+++ b/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/component/UserSelectCombo.java
@@ -22,7 +22,7 @@
public UserSelectCombo(String caption, String width) {
super(caption);
setWidth(width);
- setContainerDataSource(UserContainer.createWithData());
+ setContainerDataSource(UserContainer.getInstance());
setItemCaptionPropertyId(User.PROPERTY_DISPLAY_NAME);
setFilteringMode(ComboBox.FILTERINGMODE_CONTAINS);
setImmediate(true);
diff --git a/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/internal/container/IndexedUserContainer.java b/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/internal/container/IndexedUserContainer.java
new file mode 100644
index 0000000..f95f2a9
--- /dev/null
+++ b/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/internal/container/IndexedUserContainer.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2010-2017 SAP AG 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
+ *
+ * Contributors:
+ * SAP AG - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.skalli.view.internal.container;
+
+import java.io.Serializable;
+
+import org.eclipse.skalli.model.PropertyName;
+import org.eclipse.skalli.model.User;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+
+public class IndexedUserContainer extends IndexedContainer implements Serializable {
+
+ private static final long serialVersionUID = 632503436661743735L;
+
+ @PropertyName(position = 0)
+ public static final Object PROPERTY_USER = "user"; //$NON-NLS-1$
+
+ public IndexedUserContainer() {
+ addContainerProperty(User.PROPERTY_FIRSTNAME, String.class, null);
+ addContainerProperty(User.PROPERTY_LASTNAME, String.class, null);
+ addContainerProperty(User.PROPERTY_EMAIL, String.class, null);
+ addContainerProperty(User.PROPERTY_DISPLAY_NAME, String.class, null);
+ addContainerProperty(PROPERTY_USER, User.class, null);
+ }
+
+ public synchronized Item addItem(User user) {
+ String userId = user.getUserId();
+ Item item = getItem(userId);
+ if (item == null) {
+ item = addItem(user.getUserId()); // IndexedContainer#addItem return null, if entry already exists!!!
+ }
+ if (item != null) {
+ item.getItemProperty(User.PROPERTY_FIRSTNAME).setValue(user.getFirstname());
+ item.getItemProperty(User.PROPERTY_LASTNAME).setValue(user.getLastname());
+ item.getItemProperty(User.PROPERTY_EMAIL).setValue(user.getEmail());
+ item.getItemProperty(User.PROPERTY_DISPLAY_NAME).setValue(user.getDisplayName());
+ item.getItemProperty(PROPERTY_USER).setValue(user);
+ }
+ return item;
+ }
+}
diff --git a/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/internal/container/UserContainer.java b/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/internal/container/UserContainer.java
index e3a1304..fe9790d 100644
--- a/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/internal/container/UserContainer.java
+++ b/org.eclipse.skalli.view/src/main/java/org/eclipse/skalli/view/internal/container/UserContainer.java
@@ -10,9 +10,9 @@
*******************************************************************************/
package org.eclipse.skalli.view.internal.container;
-import java.io.Serializable;
+import static org.eclipse.skalli.view.internal.container.IndexedUserContainer.PROPERTY_USER;
+
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -20,8 +20,10 @@
import java.util.TreeSet;
import org.eclipse.skalli.model.Member;
-import org.eclipse.skalli.model.PropertyName;
import org.eclipse.skalli.model.User;
+import org.eclipse.skalli.services.event.EventListener;
+import org.eclipse.skalli.services.event.EventService;
+import org.eclipse.skalli.services.user.EventUserUpdate;
import org.eclipse.skalli.services.user.UserService;
import org.eclipse.skalli.services.user.UserServices;
@@ -29,58 +31,22 @@
import com.vaadin.data.Property;
import com.vaadin.data.util.IndexedContainer;
-public class UserContainer extends IndexedContainer implements Serializable {
+public class UserContainer implements EventListener<EventUserUpdate> {
- private static final long serialVersionUID = 632503436661743735L;
- private static UserContainer container;
+ private static IndexedUserContainer container = new IndexedUserContainer();
- @PropertyName(position = 0)
- public static final Object PROPERTY_USER = "user"; //$NON-NLS-1$
-
- private UserContainer(Collection<User> users) {
- super();
- addContainerProperty(User.PROPERTY_FIRSTNAME, String.class, null);
- addContainerProperty(User.PROPERTY_LASTNAME, String.class, null);
- addContainerProperty(User.PROPERTY_EMAIL, String.class, null);
- addContainerProperty(User.PROPERTY_DISPLAY_NAME, String.class, null);
- addContainerProperty(PROPERTY_USER, User.class, null);
- for (User user : users) {
- addItem(user);
- }
+ protected void bindEventService(EventService eventService) {
+ eventService.registerListener(EventUserUpdate.class, this);
}
- private Item addItem(User user) {
- String userId = user.getUserId();
- Item item = getItem(userId);
- if (item == null) {
- item = addItem(user.getUserId()); // IndexedContainer#addItem return null, if entry already exists!!!
- }
- if (item != null) {
- item.getItemProperty(User.PROPERTY_FIRSTNAME).setValue(user.getFirstname());
- item.getItemProperty(User.PROPERTY_LASTNAME).setValue(user.getLastname());
- item.getItemProperty(User.PROPERTY_EMAIL).setValue(user.getEmail());
- item.getItemProperty(User.PROPERTY_DISPLAY_NAME).setValue(user.getDisplayName());
- item.getItemProperty(PROPERTY_USER).setValue(user);
- }
- return item;
+ protected void unbindEventService(EventService eventService) {
+ eventService.unregisterListener(EventUserUpdate.class, this);
}
- public static synchronized UserContainer createWithData() {
- if (container == null) {
- List<User> users = Collections.emptyList();
- UserService userService = UserServices.getUserService();
- if (userService != null) {
- users = userService.getUsers();
- }
- container = new UserContainer(users);
- }
+ public static IndexedContainer getInstance() {
return container;
}
- public static void refresh() {
- container = null;
- }
-
public static User getUser(Object userId) {
if (userId instanceof User) {
return (User) userId;
@@ -120,7 +86,6 @@
}
private static Item searchAndAddUser(String userId) {
- UserContainer container = UserContainer.createWithData();
Item item = container.getItem(userId);
if (item == null) {
User user = UserServices.getUser(userId.toString());
@@ -149,7 +114,6 @@
}
public static Set<User> getUsers(Set<Member> members) {
- UserContainer container = UserContainer.createWithData();
Set<User> users = new TreeSet<User>();
Set<String> userIds = new HashSet<String>();
for (Member member : members) {
@@ -178,4 +142,15 @@
return users;
}
+ /**
+ * When the user service notifies about a change in the user base
+ * update the indexed container.
+ */
+ @Override
+ public void onEvent(EventUserUpdate event) {
+ User user = event.getUser();
+ if (user != null) {
+ container.addItem(user);
+ }
+ }
}