diff options
| author | Alex Rudyy <orudyy@apache.org> | 2013-09-14 11:24:14 +0000 |
|---|---|---|
| committer | Alex Rudyy <orudyy@apache.org> | 2013-09-14 11:24:14 +0000 |
| commit | 2af29db3885316bbb42c99f423cbc9f50619c925 (patch) | |
| tree | 3ab15a09a2bf23800834ab5c94b8c15d71d9298f /qpid/java | |
| parent | 883d7bd6a52f219984ffeb3c7fd5f7fd0bc7b1f9 (diff) | |
| download | qpid-python-2af29db3885316bbb42c99f423cbc9f50619c925.tar.gz | |
QPID-5138: Introduce preferences provider interface and its implementation storing preferences on file system
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1523217 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java')
3 files changed, 901 insertions, 0 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java new file mode 100644 index 0000000000..96d02b2ef6 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java @@ -0,0 +1,89 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +public interface PreferencesProvider extends ConfiguredObject +{ + String ID = "id"; + String NAME = "name"; + String TYPE = "type"; + String CREATED = "created"; + String UPDATED = "updated"; + String DURABLE = "durable"; + String LIFETIME_POLICY = "lifetimePolicy"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + + Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + TYPE, + CREATED, + UPDATED, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE + )); + + /** + * Returns preferences {@link Map} for a given user ID + * @param userId user ID to retrieve preferences for + * @return preferences {@link Map} + */ + Map<String, Object> getPreferences(String userId); + + /** + * Set user preferences as specified in a given {@link Map} + * @param userId user ID to set preferences for + * @param preferences new preferences + * @return existing user preferences + */ + Map<String, Object> setPreferences(String userId, Map<String, Object> preferences); + + /** + * Delete preferences for a given user ID + * @param userId user ID to delete preferences for + * @return user preferences before the deletion + */ + Map<String, Object> deletePreferences(String userId); + + /** + * Returns set of the user IDs having preferences set + * @return user IDs + */ + Set<String> listUserIDs(); + + /** + * Returns authentication provider associated with this preferences provider + * @return authentication provider + */ + AuthenticationProvider getAuthenticationProvider(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java new file mode 100644 index 0000000000..0b0610681a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java @@ -0,0 +1,566 @@ +package org.apache.qpid.server.model.adapter; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.lang.reflect.Type; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.OverlappingFileLockException; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.log4j.Logger; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.IllegalStateTransitionException; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.util.MapValueConverter; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.type.TypeReference; + +public class FileSystemPreferencesProvider extends AbstractAdapter implements PreferencesProvider +{ + private static final Logger LOGGER = Logger.getLogger(FileSystemPreferencesProvider.class); + public static String PATH = "path"; + public static final String PROVIDER_TYPE = "FileSystemPreferences"; + + // TODO: use resolver to resolve path from + // '${qpid.work_dir}/preferences/${authenticationProviderName}' + @SuppressWarnings("serial") + private static final Map<String, Object> DEFAULTS = Collections.unmodifiableMap(new HashMap<String, Object>() + {{ + put(PATH, System.getProperty("user.home") + File.separator + ".qpid" + File.separator + "preferences.json"); + put(TYPE, FileSystemPreferencesProvider.class.getSimpleName()); + }}); + + @SuppressWarnings("serial") + private static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>() + {{ + put(NAME, String.class); + put(PATH, String.class); + put(TYPE, String.class); + }}); + + @SuppressWarnings("serial") + private static Collection<String> AVAILABLE_ATTRIBUTES = Collections.unmodifiableList(new ArrayList<String>( + PreferencesProvider.AVAILABLE_ATTRIBUTES) + {{ + add(PATH); + }}); + + private final AuthenticationProvider _authenticationProvider; + private AtomicReference<State> _state; + + private final ObjectMapper _objectMapper; + private final Map<String, Map<String, Object>> _preferences; + private File _preferencesLocation; + private FileLock _fileLock; + + protected FileSystemPreferencesProvider(UUID id, Map<String, Object> attributes, AuthenticationProvider authenticationProvider, TaskExecutor taskExecutor) + { + super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); + State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING); + _state = new AtomicReference<State>(state); + addParent(AuthenticationProvider.class, authenticationProvider); + _authenticationProvider = authenticationProvider; + _objectMapper = new ObjectMapper(); + _objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + _objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + _preferences = new TreeMap<String, Map<String, Object>>(); + _preferencesLocation = new File(MapValueConverter.getStringAttribute(PATH, attributes)); + _preferences.putAll(load(_objectMapper, _preferencesLocation)); + } + + @Override + public Collection<String> getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + @Override + public String getName() + { + return (String) getAttribute(AuthenticationProvider.NAME); + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + throw new UnsupportedOperationException(); + } + + @Override + public State getActualState() + { + return _state.get(); + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + return Collections.emptySet(); + } + + @Override + public Object getAttribute(String name) + { + if (CREATED.equals(name)) + { + // TODO + } + else if (DURABLE.equals(name)) + { + return true; + } + else if (ID.equals(name)) + { + return getId(); + } + else if (LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.PERMANENT; + } + else if (STATE.equals(name)) + { + return getActualState(); + } + else if (TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if (UPDATED.equals(name)) + { + // TODO + } + return super.getAttribute(name); + } + + @Override + public boolean setState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + State state = _state.get(); + if (desiredState == State.DELETED) + { + if ((state == State.INITIALISING || state == State.ACTIVE || state == State.STOPPED || state == State.QUIESCED || state == State.ERRORED) + && _state.compareAndSet(state, State.DELETED)) + { + try + { + close(); + } + finally + { + _preferencesLocation.delete(); + _authenticationProvider.setPreferencesProvider(null); + } + return true; + } + else + { + throw new IllegalStateException("Cannot delete preferences provider in state: " + state); + } + } + else if (desiredState == State.ACTIVE) + { + if ((state == State.INITIALISING || state == State.QUIESCED || state == State.STOPPED) + && _state.compareAndSet(state, State.ACTIVE)) + { + try + { + getFileLock(); + Map<String, Map<String, Object>> preferences = load(_objectMapper, _preferencesLocation); + setPreferences(preferences); + return true; + } + catch (Exception e) + { + _state.compareAndSet(State.ACTIVE, State.ERRORED); + Broker broker = getAuthenticationProvider().getParent(Broker.class); + if (broker != null && broker.isManagementMode()) + { + LOGGER.warn("Failed to activate preferences provider: " + getName(), e); + } + else + { + throw new RuntimeException(e); + } + } + } + else + { + throw new IllegalStateException("Cannot activate preferences provider in state: " + state); + } + } + else if (desiredState == State.QUIESCED) + { + if (state == State.INITIALISING && _state.compareAndSet(state, State.QUIESCED)) + { + close(); + return true; + } + } + else if (desiredState == State.STOPPED) + { + if (_state.compareAndSet(state, State.STOPPED)) + { + close(); + return true; + } + else + { + throw new IllegalStateException("Cannot stop authentication preferences in state: " + state); + } + } + + return false; + } + + @Override + public Map<String, Object> getPreferences(String userId) + { + Map<String, Object> userPreferences = null; + synchronized (_preferences) + { + userPreferences = _preferences.get(userId); + } + if (userPreferences != null) + { + return new HashMap<String, Object>(userPreferences); + } + return Collections.emptyMap(); + } + + @Override + public Map<String, Object> setPreferences(String userId, Map<String, Object> preferences) + { + Map<String, Object> userPreferences = null; + synchronized (_preferences) + { + userPreferences = _preferences.get(userId); + if (userPreferences == null) + { + userPreferences = new HashMap<String, Object>(preferences); + _preferences.put(userId, userPreferences); + } + else + { + userPreferences.putAll(preferences); + } + savePreferences(); + } + return userPreferences; + } + + @Override + public Map<String, Object> deletePreferences(String userId) + { + Map<String, Object> userPreferences = null; + synchronized (_preferences) + { + if (_preferences.containsKey(userId)) + { + userPreferences = _preferences.remove(userId); + savePreferences(); + } + } + return userPreferences; + } + + @Override + public Set<String> listUserIDs() + { + synchronized (_preferences) + { + return Collections.unmodifiableSet(_preferences.keySet()); + } + } + + public AuthenticationProvider getAuthenticationProvider() + { + return _authenticationProvider; + } + + @Override + protected void changeAttributes(Map<String, Object> attributes) + { + Map<String, Object> effectiveAttributes = MapValueConverter.convert(super.generateEffectiveAttributes(attributes), + ATTRIBUTE_TYPES); + validateAttributes(effectiveAttributes); + String effectivePath = (String) effectiveAttributes.get(PATH); + String currentPath = (String) getAttribute(PATH); + Map<String, Map<String, Object>> newPreferences = null; + File storeFile = new File(effectivePath); + if (!effectivePath.equals(currentPath)) + { + if (!storeFile.exists()) + { + throw new IllegalConfigurationException("Path to preferences file does not exist!"); + } + newPreferences = load(_objectMapper, storeFile); + } + super.changeAttributes(attributes); + + if (newPreferences != null) + { + setPreferences(newPreferences); + _preferencesLocation = storeFile; + } + + // if provider was previously in ERRORED state then set its state to + // ACTIVE + _state.compareAndSet(State.ERRORED, State.ACTIVE); + } + + private void setPreferences(Map<String, Map<String, Object>> preferences) + { + synchronized (_preferences) + { + _preferences.clear(); + _preferences.putAll(preferences); + } + } + + private void validateAttributes(Map<String, Object> attributes) + { + super.validateChangeAttributes(attributes); + + String newName = (String) attributes.get(NAME); + String currentName = getName(); + if (!currentName.equals(newName)) + { + throw new IllegalConfigurationException("Changing the name of preferences provider is not supported"); + } + String newType = (String) attributes.get(TYPE); + String currentType = (String) getAttribute(TYPE); + if (!currentType.equals(newType)) + { + throw new IllegalConfigurationException("Changing the type of preferences provider is not supported"); + } + String path = (String) attributes.get(PATH); + if (path == null || path.equals("") || !(path instanceof String)) + { + throw new IllegalConfigurationException("Path to preferences file is not specified"); + } + } + + public File createStoreIfNotExist() + { + String path = (String)getAttribute(PATH); + File preferencesLocation = new File(path); + if (!preferencesLocation.exists()) + { + File parent = preferencesLocation.getParentFile(); + if (!parent.exists() && !parent.mkdirs()) + { + throw new IllegalConfigurationException("Cannot store preferences at " + path); + } + try + { + preferencesLocation.createNewFile(); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot store preferences at " + path); + } + } + return preferencesLocation; + } + + private Map<String, Map<String, Object>> load(ObjectMapper mapper, File file) + { + if (!file.exists() || file.length() == 0) + { + return Collections.emptyMap(); + } + + try + { + return mapper.readValue(file, new TypeReference<Map<String, Map<String, Object>>>() + { + }); + } + catch (JsonProcessingException e) + { + throw new IllegalConfigurationException("Cannot parse json", e); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot read json", e); + } + } + + private void savePreferences() + { + save(_objectMapper, _preferencesLocation, _preferences); + } + + private void save(ObjectMapper mapper, File file, Map<String, Map<String, Object>> preferences) + { + try + { + RandomAccessFile raf = new RandomAccessFile(file, "rw"); + try + { + FileChannel channel = raf.getChannel(); + try + { + FileLock lock = null; + try + { + lock = channel.tryLock(); + if (lock == null) + { + throw new IllegalConfigurationException("Cannot aquire exclusive lock on preferences file for " + + getName()); + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + mapper.writeValue(baos, preferences); + channel.write(ByteBuffer.wrap(baos.toByteArray())); + } + catch (OverlappingFileLockException e) + { + throw new IllegalConfigurationException("Cannot aquire exclusive lock on preferences file for " + + getName(), e); + } + finally + { + if (lock != null) + { + lock.release(); + } + } + } + finally + { + channel.close(); + } + } + finally + { + raf.close(); + } + } + catch (FileNotFoundException e) + { + throw new IllegalConfigurationException("Cannot find preferences file for " + getName(), e); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot store preferences file for " + getName(), e); + } + } + + private void getFileLock() throws IOException, AMQStoreException + { + File lockFile = new File(_preferencesLocation.getAbsolutePath() + ".lck"); + lockFile.createNewFile(); + + FileOutputStream out = new FileOutputStream(lockFile); + FileChannel channel = out.getChannel(); + try + { + _fileLock = channel.tryLock(); + } + catch(OverlappingFileLockException e) + { + _fileLock = null; + } + if(_fileLock == null) + { + throw new AMQStoreException("Cannot get lock on file " + lockFile.getAbsolutePath() + " is another instance running?"); + } + lockFile.deleteOnExit(); + } + + public void close() + { + try + { + releaseFileLock(); + } + catch(IOException e) + { + LOGGER.error("Cannot close file system preferences provider", e); + } + finally + { + new File(_preferencesLocation.getAbsolutePath() + ".lck").delete(); + _fileLock = null; + _preferences.clear(); + } + } + + private void releaseFileLock() throws IOException + { + _fileLock.release(); + _fileLock.channel().close(); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java new file mode 100644 index 0000000000..bb64241ff0 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java @@ -0,0 +1,246 @@ +package org.apache.qpid.server.model.adapter; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class FileSystemPreferencesProviderTest extends QpidTestCase +{ + private static final String TEST_PREFERENCES = "{\"user1\":{\"pref1\":\"pref1User1Value\", \"pref2\": true, \"pref3\": 1.0, \"pref4\": 2}," + + "\"user2\":{\"pref1\":\"pref1User2Value\", \"pref2\": false, \"pref3\": 2.0, \"pref4\": 3}}"; + private FileSystemPreferencesProvider _preferencesProvider; + private AuthenticationProvider _authenticationProvider; + private Broker _broker; + private String _user1, _user2; + private File _preferencesFile; + + protected void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _authenticationProvider = mock(AuthenticationProvider.class); + _user1 = "user1"; + _user2 = "user2"; + _preferencesFile = TestFileUtils.createTempFile(this, ".prefs.json", TEST_PREFERENCES); + + _broker = BrokerTestHelper.createBrokerMock(); + TaskExecutor taslExecutor = mock(TaskExecutor.class); + when(taslExecutor.isTaskExecutorThread()).thenReturn(true); + when(_broker.getTaskExecutor()).thenReturn(taslExecutor); + when(_authenticationProvider.getParent(Broker.class)).thenReturn(_broker); + } + + protected void tearDown() throws Exception + { + try + { + BrokerTestHelper.tearDown(); + _preferencesFile.delete(); + } + finally + { + super.tearDown(); + } + } + + public void testConstructionWithExistingFile() + { + _preferencesProvider = createPreferencesProvider(); + assertEquals(State.INITIALISING, _preferencesProvider.getActualState()); + } + + public void testConstructionWithNonExistingFile() + { + File nonExistingFile = new File(TMP_FOLDER, "preferences-" + UUID.randomUUID() + ".json"); + assertFalse("Preferences file exists", nonExistingFile.exists()); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, nonExistingFile.getAbsolutePath()); + _preferencesProvider = new FileSystemPreferencesProvider(UUID.randomUUID(), attributes, _authenticationProvider, _broker.getTaskExecutor()); + _preferencesProvider.createStoreIfNotExist(); + assertEquals(State.INITIALISING, _preferencesProvider.getActualState()); + assertTrue("Preferences file was not created", nonExistingFile.exists()); + } + finally + { + nonExistingFile.delete(); + } + } + + public void testConstructionWithEmptyFile() throws Exception + { + File emptyPrefsFile = new File(TMP_FOLDER, "preferences-" + UUID.randomUUID() + ".json"); + emptyPrefsFile.createNewFile(); + assertTrue("Preferences file does notexists", emptyPrefsFile.exists()); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, emptyPrefsFile.getAbsolutePath()); + _preferencesProvider = new FileSystemPreferencesProvider(UUID.randomUUID(), attributes, _authenticationProvider, _broker.getTaskExecutor()); + assertEquals(State.INITIALISING, _preferencesProvider.getActualState()); + } + finally + { + emptyPrefsFile.delete(); + } + } + + public void testActivate() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + assertEquals("Unexpexpected state", State.ACTIVE, _preferencesProvider.getActualState()); + } + + public void testChangeAttributes() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + File newPrefsFile = TestFileUtils.createTempFile(this, ".prefs.json", "{\"user3\":{\"pref1\":\"pref1User3Value\", \"pref3\": 2.0}}"); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, newPrefsFile.getAbsolutePath()); + _preferencesProvider.changeAttributes(attributes); + assertEquals("Unexpected path", newPrefsFile.getAbsolutePath(), + _preferencesProvider.getAttribute(FileSystemPreferencesProvider.PATH)); + + Map<String, Object> preferences1 = _preferencesProvider.getPreferences(_user1); + assertTrue("Unexpected preferences for user1", preferences1.isEmpty()); + + String user3 = "user3"; + Map<String, Object> preferences3 = _preferencesProvider.getPreferences(user3); + assertFalse("No preference found for user3", preferences3.isEmpty()); + assertEquals("Unexpected preference 1 for user 3", "pref1User3Value", preferences3.get("pref1")); + assertEquals("Unexpected preference 3 for user 3", 2.0, ((Number) preferences3.get("pref3")).floatValue(), 0.01); + } + finally + { + newPrefsFile.delete(); + } + } + + public void testGetPreferences() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + Map<String, Object> preferences1 = _preferencesProvider.getPreferences(_user1); + assertUser1Preferences(preferences1); + + Map<String, Object> preferences2 = _preferencesProvider.getPreferences(_user2); + assertUser2Preferences(preferences2); + + String user3 = "user3"; + Map<String, Object> preferences3 = _preferencesProvider.getPreferences(user3); + assertTrue("No preference found for user3", preferences3.isEmpty()); + } + + public void testSetPrefernces() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + Map<String, Object> newPreferences = new HashMap<String, Object>(); + newPreferences.put("pref2", false); + newPreferences.put("pref4", 8); + Map<String, Object> pref5 = new HashMap<String, Object>(); + pref5.put("test1", "test1Value"); + pref5.put("test2", 5); + newPreferences.put("pref5", pref5); + + _preferencesProvider.setPreferences(_user1, newPreferences); + + FileSystemPreferencesProvider newProvider = createPreferencesProvider(); + Map<String, Object> preferences1 = newProvider.getPreferences(_user1); + assertNotNull("Preferences should not be null for user 1", preferences1); + assertEquals("Unexpected preference 1 for user 1", "pref1User1Value", preferences1.get("pref1")); + assertEquals("Unexpected preference 2 for user 1", false, preferences1.get("pref2")); + assertEquals("Unexpected preference 3 for user 1", 1.0, ((Number) preferences1.get("pref3")).floatValue(), 0.01); + assertEquals("Unexpected preference 4 for user 1", 8, preferences1.get("pref4")); + assertNotNull("Unexpected preference 5 for user 1", preferences1.get("pref5")); + assertEquals("Unexpected preference 5 for user 1", pref5, preferences1.get("pref5")); + + Map<String, Object> preferences2 = newProvider.getPreferences(_user2); + assertUser2Preferences(preferences2); + + String user3 = "user3"; + Map<String, Object> preferences3 = newProvider.getPreferences(user3); + assertTrue("No preference found for user3", preferences3.isEmpty()); + } + + public void testDeletePrefernces() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + _preferencesProvider.deletePreferences(_user1); + + FileSystemPreferencesProvider newProvider = createPreferencesProvider(); + Map<String, Object> preferences1 = newProvider.getPreferences(_user1); + assertTrue("Preferences should not be set for user 1", preferences1.isEmpty()); + + Map<String, Object> preferences2 = newProvider.getPreferences(_user2); + assertUser2Preferences(preferences2); + + String user3 = "user3"; + Map<String, Object> preferences3 = newProvider.getPreferences(user3); + assertTrue("No preference found for user3", preferences3.isEmpty()); + } + + public void testListUserNames() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + Set<String> userNames = _preferencesProvider.listUserIDs(); + + assertEquals("Unexpected user names", new HashSet<String>(Arrays.asList("user1", "user2")), userNames); + } + + private FileSystemPreferencesProvider createPreferencesProvider() + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesFile.getAbsolutePath()); + attributes.put(FileSystemPreferencesProvider.NAME, "test"); + return _preferencesProvider = new FileSystemPreferencesProvider(UUID.randomUUID(), attributes, _authenticationProvider, _broker.getTaskExecutor()); + } + + private void assertUser1Preferences(Map<String, Object> preferences1) + { + assertNotNull("Preferences should not be null for user 1", preferences1); + assertEquals("Unexpected preference 1 for user 1", "pref1User1Value", preferences1.get("pref1")); + assertEquals("Unexpected preference 2 for user 1", true, preferences1.get("pref2")); + assertEquals("Unexpected preference 3 for user 1", 1.0, ((Number) preferences1.get("pref3")).floatValue(), 0.01); + assertEquals("Unexpected preference 4 for user 1", 2, preferences1.get("pref4")); + assertNull("Unexpected preference 5 for user 1", preferences1.get("pref5")); + } + + private void assertUser2Preferences(Map<String, Object> preferences2) + { + assertNotNull("Preferences should not be null for user 2", preferences2); + assertEquals("Unexpected preference 1 for user 2", "pref1User2Value", preferences2.get("pref1")); + assertEquals("Unexpected preference 2 for user 2", false, preferences2.get("pref2")); + assertEquals("Unexpected preference 2 for user 2", 2.0, ((Number) preferences2.get("pref3")).floatValue(), 0.01); + assertEquals("Unexpected preference 3 for user 2", 3, preferences2.get("pref4")); + assertNull("Unexpected preference 5 for user 2", preferences2.get("pref5")); + } +} |
