mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-17 01:31:01 +00:00
Initial implementation to register PreferenceConverters on the UserStore
and set/get preference objects that are being held in memory for fast access
This commit is contained in:
1 parent
b404b42196
commit
d77f6adb43
2 files changed
+141
-2
No files matched your search
+117
@@ -7,10 +7,12 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
|
||||
import com.sap.sse.security.PreferenceConverter;
|
||||
import com.sap.sse.security.SocialSettingsKeys;
|
||||
import com.sap.sse.security.User;
|
||||
import com.sap.sse.security.UserStore;
|
||||
@@ -48,6 +50,18 @@ public class UserStoreImpl implements UserStore {
|
||||
*/
|
||||
private final ConcurrentHashMap<String, Map<String, String>> preferences;
|
||||
|
||||
/**
|
||||
* Converter objects to map preference Strings to Objects.
|
||||
* The keys must match the keys of the preferences.
|
||||
*/
|
||||
private final ConcurrentHashMap<String, PreferenceConverter<?>> preferenceConverters;
|
||||
|
||||
/**
|
||||
* This is another view of the String preferences mapped by {@link #preferenceConverters} to Objects.
|
||||
* Keys are the usernames, values are the key/value pairs representing the user's preferences.
|
||||
*/
|
||||
private final ConcurrentHashMap<String, Map<String, Object>> preferenceObjects;
|
||||
|
||||
/**
|
||||
* Won't be serialized and remains <code>null</code> on the de-serializing end.
|
||||
*/
|
||||
@@ -65,6 +79,8 @@ public class UserStoreImpl implements UserStore {
|
||||
settingTypes = new ConcurrentHashMap<>();
|
||||
usersByAccessToken = new ConcurrentHashMap<>();
|
||||
preferences = new ConcurrentHashMap<>();
|
||||
preferenceConverters = new ConcurrentHashMap<>();
|
||||
preferenceObjects = new ConcurrentHashMap<>();
|
||||
this.mongoObjectFactory = mongoObjectFactory;
|
||||
if (domainObjectFactory != null) {
|
||||
for (Entry<String, Class<?>> e : domainObjectFactory.loadSettingTypes().entrySet()) {
|
||||
@@ -105,6 +121,8 @@ public class UserStoreImpl implements UserStore {
|
||||
@Override
|
||||
public void clear() {
|
||||
preferences.clear();
|
||||
preferenceConverters.clear();
|
||||
preferenceObjects.clear();
|
||||
emailForUsername.clear();
|
||||
settings.clear();
|
||||
settingTypes.clear();
|
||||
@@ -405,6 +423,11 @@ public class UserStoreImpl implements UserStore {
|
||||
|
||||
@Override
|
||||
public void setPreference(String username, String key, String value) {
|
||||
setPreferenceInternal(username, key, value);
|
||||
loadPreferenceIfConverterIsAvailable(username, key);
|
||||
}
|
||||
|
||||
private void setPreferenceInternal(String username, String key, String value) {
|
||||
Map<String, String> userMap = preferences.get(username);
|
||||
if (userMap == null) {
|
||||
synchronized (preferences) {
|
||||
@@ -431,6 +454,7 @@ public class UserStoreImpl implements UserStore {
|
||||
mongoObjectFactory.storePreferences(username, userMap);
|
||||
}
|
||||
}
|
||||
unsetPreferenceObject(username, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -466,4 +490,97 @@ public class UserStoreImpl implements UserStore {
|
||||
public Map<String, Class<?>> getAllSettingTypes() {
|
||||
return settingTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPreferenceConverter(String preferenceKey, PreferenceConverter<?> converter) {
|
||||
PreferenceConverter<?> alreadyAssociatedConverter = preferenceConverters.putIfAbsent(preferenceKey, converter);
|
||||
|
||||
if(alreadyAssociatedConverter == null) {
|
||||
final Set<String> usersToProcess = new HashSet<>(preferences.keySet());
|
||||
for (String user : usersToProcess) {
|
||||
loadPreferenceWithConverter(user, preferenceKey, converter);
|
||||
}
|
||||
} else {
|
||||
logger.log(Level.SEVERE, "PreferenceConverter " + alreadyAssociatedConverter + " for key " + preferenceKey
|
||||
+ " is already registered. Converter " + converter + " will not be registered");
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPreferenceIfConverterIsAvailable(String username, String key) {
|
||||
PreferenceConverter<?> preferenceConverter = preferenceConverters.get(key);
|
||||
if (preferenceConverter != null) {
|
||||
loadPreferenceWithConverter(username, key, preferenceConverter);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPreferenceWithConverter(String username, String key, PreferenceConverter<?> preferenceConverter) {
|
||||
final String preferenceString = getPreference(username, key);
|
||||
if (preferenceString != null) {
|
||||
try {
|
||||
final Object convertedObject = preferenceConverter.toPreference(preferenceString);
|
||||
setPreferenceObjectInternal(username, key, convertedObject);
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.SEVERE, "Error while converting preference for key " + key + " from String \""
|
||||
+ preferenceString + "\"", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreferenceObjectInternal(String username, String key, final Object convertedObject) {
|
||||
Map<String, Object> userMap = preferenceObjects.get(username);
|
||||
if (userMap == null) {
|
||||
synchronized (preferenceObjects) {
|
||||
// only synchronize when necessary
|
||||
userMap = preferenceObjects.get(username);
|
||||
if (userMap == null) {
|
||||
userMap = new ConcurrentHashMap<>();
|
||||
preferenceObjects.put(username, userMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
userMap.put(key, convertedObject);
|
||||
}
|
||||
|
||||
private void unsetPreferenceObject(String username, String key) {
|
||||
Map<String, Object> userObjectMap = preferenceObjects.get(username);
|
||||
if (userObjectMap != null) {
|
||||
userObjectMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getPreferenceObject(String username, String key) {
|
||||
final Object result;
|
||||
Map<String, Object> userMap = preferenceObjects.get(username);
|
||||
if (userMap != null) {
|
||||
result = userMap.get(key);
|
||||
} else {
|
||||
result = null;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
T resultT = (T) result;
|
||||
return resultT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void setPreferenceObject(String username, String key, Object preferenceObject)
|
||||
throws IllegalArgumentException {
|
||||
@SuppressWarnings("unchecked")
|
||||
PreferenceConverter<Object> preferenceConverter = (PreferenceConverter<Object>) preferenceConverters.get(key);
|
||||
if (preferenceConverter == null) {
|
||||
throw new IllegalArgumentException("Setting preference for key "+key+" but there is no converter associated!");
|
||||
}
|
||||
if(preferenceObject == null) {
|
||||
unsetPreference(username, key);
|
||||
} else {
|
||||
try {
|
||||
String stringPreference = preferenceConverter.toString(preferenceObject);
|
||||
setPreferenceInternal(username, key, stringPreference);
|
||||
setPreferenceObjectInternal(username, key, preferenceObject);
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.SEVERE, "Error while converting preference for key " + key + " from Object \""
|
||||
+ preferenceObject + "\"", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,30 @@ public interface UserStore extends Named {
|
||||
void unsetPreference(String username, String key);
|
||||
|
||||
String getPreference(String username, String key);
|
||||
|
||||
/**
|
||||
* Registers a converter objects for a preference key that is used to convert preference Strings to Objects. This
|
||||
* makes it possible to access deserialized settings without the need to do the deserialization over and over again.
|
||||
*
|
||||
* @param key the key to associate the converter with
|
||||
* @param converter the converter to use for (de)serialization
|
||||
*/
|
||||
void registerPreferenceConverter(String key, PreferenceConverter<?> converter);
|
||||
|
||||
/**
|
||||
* Gets a preference object. Always returns null if there is no converter associated with the given key -> see
|
||||
* {@link #registerPreferenceConverter(String, PreferenceConverter)}.
|
||||
*/
|
||||
<T> T getPreferenceObject(String username, String key);
|
||||
|
||||
/**
|
||||
* Sets a preference as Object. This converts the given Object to a preference String using a
|
||||
* {@link PreferenceConverter} that was registered through
|
||||
* {@link #registerPreferenceConverter(String, PreferenceConverter)}.
|
||||
*
|
||||
* @throws IllegalArgumentException if there is no {@link PreferenceConverter} registered with the given key.
|
||||
*/
|
||||
<T> void setPreferenceObject(String username, String key, Object preferenceObject) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Sets a value for a key if that key was previously added to this store using {@link #addSetting(String, Class)}.
|
||||
@@ -106,6 +130,4 @@ public interface UserStore extends Named {
|
||||
* {@code username} no access token has previously been {@link #setAccessToken(String, String) set}.
|
||||
*/
|
||||
String getAccessToken(String username);
|
||||
|
||||
// void registerPreferenceConverter(String preferenceKey, PreferenceConverter<?> converter);
|
||||
}
|
||||
Reference in new issue
Block a user