Author: scottbw
Date: Wed Feb 12 16:50:40 2014
New Revision: 1567675

URL: http://svn.apache.org/r1567675
Log:
Added the Redis implementation of the preferences SPI

Added:
    wookie/trunk/wookie-services/wookie-redis/README
    wookie/trunk/wookie-services/wookie-redis/src/
    wookie/trunk/wookie-services/wookie-redis/src/main/
    wookie/trunk/wookie-services/wookie-redis/src/main/java/
    wookie/trunk/wookie-services/wookie-redis/src/main/java/org/
    wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/
    wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/
    
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/
    
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/
    
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisPreferencesService.java
    wookie/trunk/wookie-services/wookie-redis/src/test/
    wookie/trunk/wookie-services/wookie-redis/src/test/java/
    wookie/trunk/wookie-services/wookie-redis/src/test/java/org/
    wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/
    wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/
    
wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/
    
wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/
    
wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisPreferencesServiceTest.java
Modified:
    wookie/trunk/wookie-services/wookie-redis/pom.xml

Added: wookie/trunk/wookie-services/wookie-redis/README
URL: 
http://svn.apache.org/viewvc/wookie/trunk/wookie-services/wookie-redis/README?rev=1567675&view=auto
==============================================================================
--- wookie/trunk/wookie-services/wookie-redis/README (added)
+++ wookie/trunk/wookie-services/wookie-redis/README Wed Feb 12 16:50:40 2014
@@ -0,0 +1,9 @@
+This is a Redis implementation of the Wookie SPI
+
+To use it, place a file called org.apache.wookie.services.PreferencesService 
in META-INF/services of swookie-server. 
+
+This file should just contain the line:
+
+org.apache.wookie.services.redis.RedisPreferencesService
+
+This will make wookie-server start up using the Redis preferences 
implemetnation instead of the default in-memory preferences store.
\ No newline at end of file

Modified: wookie/trunk/wookie-services/wookie-redis/pom.xml
URL: 
http://svn.apache.org/viewvc/wookie/trunk/wookie-services/wookie-redis/pom.xml?rev=1567675&r1=1567674&r2=1567675&view=diff
==============================================================================
--- wookie/trunk/wookie-services/wookie-redis/pom.xml (original)
+++ wookie/trunk/wookie-services/wookie-redis/pom.xml Wed Feb 12 16:50:40 2014
@@ -48,6 +48,25 @@
             <type>jar</type>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+               <groupId>org.json</groupId>
+               <artifactId>json</artifactId>
+               <version>20131018</version>
+               <type>jar</type>
+               <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.7</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>uk.co.datumedge</groupId>
+            <artifactId>redis-launcher</artifactId>
+            <version>0.3</version>
+            <optional>true</optional>
+       </dependency>
     </dependencies>
   
 </project>
\ No newline at end of file

Added: 
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisPreferencesService.java
URL: 
http://svn.apache.org/viewvc/wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisPreferencesService.java?rev=1567675&view=auto
==============================================================================
--- 
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisPreferencesService.java
 (added)
+++ 
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisPreferencesService.java
 Wed Feb 12 16:50:40 2014
@@ -0,0 +1,258 @@
+/*
+ *  Licensed 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.wookie.services.redis;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.wookie.beans.IPreference;
+import org.apache.wookie.services.PreferencesService;
+import org.apache.wookie.services.impl.DefaultPreferenceImpl;
+import org.json.JSONObject;
+
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+/**
+ * An implementation of a PreferencesService using Redis as the backend
+ */
+public class RedisPreferencesService implements PreferencesService {
+       
+       /**
+        * The thread pool for jedis
+        */
+       private JedisPool pool;
+       
+       public RedisPreferencesService(){
+               pool = new JedisPool(new JedisPoolConfig(), "localhost");
+       }
+
+       private IPreference getPreferenceObject(String token, String name){
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Get the jedis key for this pref object
+               //
+               String key = getKey(token, name);
+               
+               //
+               // Get the value from redis
+               //
+               String result = jedis.get(key);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // Convert the value back into an IPreference and return it
+               //
+               return rehydrate(result);               
+       }
+       
+       @Override
+       public void setPreference(String token, IPreference preference) {
+               
+               //
+               // Check if the preference is null - if so, do nothing
+               // TODO throw an exception, or log a warning
+               //
+               if (preference == null) return;
+               
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Get the redis key to use for this pref
+               //
+               String key = getKey(token, preference.getName());
+               
+               //
+               // If there is no existing tuple, add the key to the list of 
keys for this token
+               //
+               if (getPreference(token, preference.getName()) == null){
+                       jedis.lpush(token, key);                        
+               }
+
+               //
+               // Convert the IPreference into JSON for storage
+               //
+               String preferenceJson = dehydrate(preference);
+               
+               //
+               // Store the preference
+               //
+               jedis.set(key, preferenceJson);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+       }
+       
+       //////
+       
+       @Override
+       public String getPreference(String token, String name) {
+               IPreference preference = getPreferenceObject(token, name);
+               if (preference == null) return null;
+               return preference.getValue();
+       }
+
+       @Override
+       public void setPreference(String token, String name, String value) {
+               DefaultPreferenceImpl pref = new DefaultPreferenceImpl(name, 
value, false);
+               setPreference(token, pref);
+       }
+
+       @Override
+       public void setPreference(String token, String name, String value,
+                       boolean readOnly) {
+               DefaultPreferenceImpl pref = new DefaultPreferenceImpl(name, 
value, readOnly);
+               setPreference(token, pref);
+       }
+
+       //////
+
+
+       @Override
+       public Collection<IPreference> getPreferences(String token) {
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Get the list of keys for the token
+               //
+               List<String> keys = jedis.lrange(token, 0, 999);
+               ArrayList<IPreference> preferences = new 
ArrayList<IPreference>();
+               for (String key: keys){
+                       
+                       //
+                       // Get the IPreference for each key on the list and 
+                       // add it to the arraylist
+                       //
+                       String json = jedis.get(key);
+                       IPreference pref = rehydrate(json);
+                       preferences.add(pref);
+               }
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+                       
+               //
+               // Return the arraylist
+               //
+               return preferences;
+       }
+
+       @Override
+       public void setPreferences(String token, Collection<IPreference> 
preferences) {
+               
+               //
+               // Clear the token
+               //
+               removePreferences(token);
+               
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Add the preferences to the list
+               //
+               if (preferences != null){
+                       for (IPreference pref: preferences){
+                               setPreference(token, pref);
+                       }
+               }
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+       }
+
+       @Override
+       public void removePreferences(String token) {
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+
+               //
+               // Remove everything linked from the preferences list
+               //
+               List<String> keys = jedis.lrange(token, 0, 999);
+               for (String key: keys){
+                       jedis.del(key);
+               }
+               
+               //
+               // Remove the existing preference list
+               //
+               jedis.del(token);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+       }
+       
+       ////// Utilities
+       
+       /**
+        * Convert a JSON string into an IPreference instance
+        */
+       private IPreference rehydrate(String input){
+               if (input == null) return null;
+               JSONObject json = new JSONObject(input);
+               DefaultPreferenceImpl pref = new 
DefaultPreferenceImpl(json.getString("name"), json.getString("value"), 
json.getBoolean("readOnly"));
+               return pref;
+       }
+       
+       /**
+        * Convert an IPreference instance into a JSON String
+        */
+       private String dehydrate(IPreference pref){
+               JSONObject json = new JSONObject();
+               json.put("name", pref.getName());
+               json.put("value", pref.getValue());
+               json.put("readOnly", pref.isReadOnly());
+               return json.toString();
+       }
+       
+       /**
+        * Gets the redis key to use for a combination of token and pref name
+        * @param token the token
+        * @param name the preference name
+        * @return the redis key to use for getting and setting the pref
+        */
+       private String getKey(String token, String name){
+               return "pref::" + token + "::" + name;
+       }
+
+}

Added: 
wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisPreferencesServiceTest.java
URL: 
http://svn.apache.org/viewvc/wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisPreferencesServiceTest.java?rev=1567675&view=auto
==============================================================================
--- 
wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisPreferencesServiceTest.java
 (added)
+++ 
wookie/trunk/wookie-services/wookie-redis/src/test/java/org/apache/wookie/services/redis/RedisPreferencesServiceTest.java
 Wed Feb 12 16:50:40 2014
@@ -0,0 +1,229 @@
+/*
+ *  Licensed 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.wookie.services.redis;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Properties;
+
+import org.apache.wookie.services.impl.DefaultPreferenceImpl;
+import org.apache.wookie.beans.IPreference;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import redis.clients.jedis.Jedis;
+
+import uk.co.datumedge.redislauncher.LocalRedisServer;
+import uk.co.datumedge.redislauncher.RedisServer;
+
+public class RedisPreferencesServiceTest {
+       
+       private static RedisServer redisServer;
+       private static RedisPreferencesService svc;
+       
+       @BeforeClass
+       public static void setup() throws IOException, InterruptedException{
+               //
+               // Set the path to the Redis executable so we can start a test 
instance
+               //
+               Properties props = System.getProperties();
+               props.setProperty("redislauncher.command", 
"/usr/local/bin/redis-server");
+               redisServer = LocalRedisServer.newInstance();
+               redisServer.start();
+
+               svc = new RedisPreferencesService();
+               Jedis jedis = new Jedis("localhost");
+               jedis.flushDB();
+       }
+       
+       @AfterClass
+       public static void tearDown() throws IOException, InterruptedException{
+               svc = null;
+               redisServer.stop();
+       }
+
+       @After
+       public void cleanUp(){
+               svc.removePreferences("token");
+       }
+       
+       @Test
+       public void getNull(){
+               String result = svc.getPreference("token", "test-null");
+               assertEquals(null, result);
+       }
+       
+       @Test
+       public void setAndGet(){                
+               svc.setPreference("token", "test", "test");
+               String result = svc.getPreference("token", "test");
+               assertEquals("test", result);
+       }
+       
+       @Test
+       public void setAndUpdate(){             
+               svc.setPreference("token", "test", "test");
+               String result = svc.getPreference("token", "test");
+               assertEquals("test", result);
+               svc.setPreference("token", "test", "test-updated");
+               result = svc.getPreference("token", "test");
+               assertEquals("test-updated", result);
+       }
+       
+       @Test
+       public void setAndGetByString(){        
+               svc.setPreference("token", "test", "test-value", true);
+               Collection<IPreference> prefs = svc.getPreferences("token");
+               assertEquals(1, prefs.size());
+               IPreference pref = prefs.iterator().next();
+               
+               assertEquals("test", pref.getName());
+               assertEquals("test-value", pref.getValue());
+               assertEquals(true, pref.isReadOnly());
+       }
+       
+       @Test
+       public void setAndGetByObject(){        
+               IPreference pref = new DefaultPreferenceImpl("test", 
"test-value", true);
+               svc.setPreference("token", pref);
+               Collection<IPreference> prefs = svc.getPreferences("token");
+               assertEquals(1, prefs.size());
+               pref = prefs.iterator().next();
+               
+               assertEquals("test", pref.getName());
+               assertEquals("test-value", pref.getValue());
+               assertEquals(true, pref.isReadOnly());
+       }
+       
+       @Test
+       public void setAndGetByObjectNull(){    
+               svc.setPreference("token", null);
+               Collection<IPreference> prefs = svc.getPreferences("token");
+               assertEquals(0, prefs.size());
+       }
+       
+       @Test
+       public void setCollection(){
+               ArrayList<IPreference> preferences = new 
ArrayList<IPreference>();
+               IPreference preference1 = new 
DefaultPreferenceImpl("test-name1", "test-value1", true);
+               IPreference preference2 = new 
DefaultPreferenceImpl("test-name2", "test-value2", false);
+               preferences.add(preference1);
+               preferences.add(preference2);
+               
+               svc.setPreferences("token", preferences);
+               
+               Collection<IPreference> returned = svc.getPreferences("token");
+               assertEquals(2, returned.size());
+       }
+       
+       @Test
+       public void resetCollection(){
+               ArrayList<IPreference> preferences = new 
ArrayList<IPreference>();
+               IPreference preference1 = new 
DefaultPreferenceImpl("test-name1", "test-value1", true);
+               IPreference preference2 = new 
DefaultPreferenceImpl("test-name2", "test-value2", false);
+               preferences.add(preference1);
+               preferences.add(preference2);
+               
+               svc.setPreferences("token", preferences);
+               
+               Collection<IPreference> returned = svc.getPreferences("token");
+               assertEquals(2, returned.size());
+               
+               preferences.remove(preference2);
+               svc.setPreferences("token", preferences);
+               returned = svc.getPreferences("token");
+               assertEquals(1, returned.size());
+       }
+       
+       @Test
+       public void setCollectionNull(){
+               
+               svc.setPreferences("token", null);
+               
+               Collection<IPreference> returned = svc.getPreferences("token");
+               assertEquals(0, returned.size());
+       }
+       
+       @Test
+       public void resetCollectionNull(){
+               ArrayList<IPreference> preferences = new 
ArrayList<IPreference>();
+               IPreference preference1 = new 
DefaultPreferenceImpl("test-name1", "test-value1", true);
+               IPreference preference2 = new 
DefaultPreferenceImpl("test-name2", "test-value2", false);
+               preferences.add(preference1);
+               preferences.add(preference2);
+               
+               svc.setPreferences("token", preferences);
+               
+               Collection<IPreference> returned = svc.getPreferences("token");
+               assertEquals(2, returned.size());
+               
+               svc.setPreferences("token", null);
+               returned = svc.getPreferences("token");
+               assertEquals(0, returned.size());
+       }
+       
+       
+       @Test
+       public void setAndGetObject(){          
+               IPreference preference = new DefaultPreferenceImpl("test-name", 
"test-value", false);
+               
+               svc.setPreference("token", preference);
+               
+               String result = svc.getPreference("token", "test-name");
+               
+               assertEquals("test-value", result);
+       }
+       
+       @Test
+       public void setAndGetObjects(){
+               
+               IPreference preference1 = new 
DefaultPreferenceImpl("test-name", "test-value", false);
+               IPreference preference2 = new 
DefaultPreferenceImpl("test-name2", "test-value2", false);
+
+               svc.setPreference("token", preference1);
+               svc.setPreference("token", preference2);
+               
+               String result = svc.getPreference("token", "test-name");
+               assertEquals("test-value", result);
+               
+               result = svc.getPreference("token", "test-name2");
+               assertEquals("test-value2", result);            
+       }
+       
+       @Test
+       public void getNothing(){
+                                               
+               String result = svc.getPreference("token", "test-name3");
+               
+               assertEquals(null, result);
+       }
+       
+       @Test
+       public void setAndReset(){
+
+               svc.setPreference("token", "test-reset", "1");
+               svc.setPreference("token", "test-reset", "2");
+               assertEquals("2", svc.getPreference("token", "test-reset"));
+               assertEquals("2", svc.getPreference("token", "test-reset"));
+               svc.setPreference("token", "test-reset", "1");
+               assertEquals("1", svc.getPreference("token", "test-reset"));
+               assertEquals("1", svc.getPreference("token", "test-reset"));
+       }
+
+}


Reply via email to