You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2013/09/14 13:24:14 UTC

svn commit: r1523217 - in /qpid/trunk/qpid/java/broker/src: main/java/org/apache/qpid/server/model/ main/java/org/apache/qpid/server/model/adapter/ test/java/org/apache/qpid/server/model/adapter/

Author: orudyy
Date: Sat Sep 14 11:24:14 2013
New Revision: 1523217

URL: http://svn.apache.org/r1523217
Log:
QPID-5138: Introduce preferences provider interface and its implementation storing preferences on file system

Added:
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java
    qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java
    qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java?rev=1523217&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java Sat Sep 14 11:24:14 2013
@@ -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();
+}

Added: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java?rev=1523217&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java (added)
+++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java Sat Sep 14 11:24:14 2013
@@ -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();
+    }
+}

Added: qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java?rev=1523217&view=auto
==============================================================================
--- qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java (added)
+++ qpid/trunk/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java Sat Sep 14 11:24:14 2013
@@ -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"));
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org