Author: scottbw
Date: Thu Feb 13 10:45:40 2014
New Revision: 1567878

URL: http://svn.apache.org/r1567878
Log:
First commit of SharedContextService provider using Redis

Added:
    
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java

Added: 
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java
URL: 
http://svn.apache.org/viewvc/wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java?rev=1567878&view=auto
==============================================================================
--- 
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java
 (added)
+++ 
wookie/trunk/wookie-services/wookie-redis/src/main/java/org/apache/wookie/services/redis/RedisSharedContextService.java
 Thu Feb 13 10:45:40 2014
@@ -0,0 +1,500 @@
+/*
+ *  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.List;
+
+import org.apache.wookie.beans.IParticipant;
+import org.apache.wookie.beans.ISharedData;
+import org.apache.wookie.services.SharedContextService;
+import org.apache.wookie.services.impl.DefaultParticipantImpl;
+import org.apache.wookie.services.impl.DefaultSharedDataImpl;
+import org.json.JSONObject;
+
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+/**
+ * SharedContext SPI implementation using a Redis nosql database.
+ */
+public class RedisSharedContextService implements SharedContextService {
+       
+       /**
+        * The thread pool for jedis
+        */
+       private JedisPool pool;
+       
+       public RedisSharedContextService(){
+               pool = new JedisPool(new JedisPoolConfig(), "localhost");
+       }
+       
+       ////// Data API
+
+       @Override
+       public ISharedData[] getSharedData(String apiKey, String widgetId,
+                       String contextId) {
+               //
+               // get the redis context key
+               //
+               String context = this.getContextKey(apiKey, widgetId, 
contextId);
+               
+               //
+               // get a jedis connector
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Get the context list
+               //
+               List<String> keys = jedis.lrange(context, 0, 999);
+               ArrayList<ISharedData> data = new ArrayList<ISharedData>();
+               
+               //
+               // For each item in the list, if its a data object, get 
+               // it and add it to the array
+               //
+               for (String key: keys){
+                       
+                       //
+                       // Get the ISharedData for each key on the list and 
+                       // add it to the arraylist
+                       //
+                       if (key.startsWith("data")){
+                       String json = jedis.get(key);
+                       ISharedData item = rehydrateData(json);
+                       data.add(item);
+                       }
+               }
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // Return the array of ISharedData objects
+               //
+               return data.toArray(new ISharedData[data.size()]);
+       }
+
+       @Override
+       public ISharedData getSharedData(String apiKey, String widgetId,
+                       String contextId, String name) {
+
+               //
+               // Get the key
+               //
+               String key = this.getDataKey(apiKey, widgetId, contextId, name);
+               
+               //
+               // get a jedis connector
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // get an object from the store and rehydrate it from json
+               //
+               String json = jedis.get(key);
+               ISharedData data = rehydrateData(json);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // Return the object
+               //
+               return data;
+       }
+
+       @Override
+       public boolean removeSharedData(String apiKey, String widgetId,
+                       String contextId, String name) {
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // get the Redis key for the participant
+               //
+               String key = this.getDataKey(apiKey, widgetId, contextId, name);
+               
+               //
+               // if it doesn't exist, return false
+               //
+               if ( this.getSharedData(apiKey, widgetId, contextId, name) == 
null){
+                       return false;
+               }
+                               
+               //
+               // Delete the object
+               //
+               jedis.del(key);
+               
+               //
+               // Remove the key from the context list
+               //
+               String context = this.getContextKey(apiKey, widgetId, 
contextId);
+               jedis.lrem(context, 0, key);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // OK
+               //
+               return true;
+       }
+
+       public boolean updateSharedData(String apiKey, String widgetId,
+                       String contextId, ISharedData data, boolean append) {
+               //
+               // Check if the data is null
+               //
+               if (data == null) return false;
+               
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Get the redis key to use for this 
+               //
+               String key = getDataKey(apiKey, widgetId, contextId, 
data.getDkey());
+               String context = getContextKey(apiKey, widgetId, contextId);
+               
+               //
+               // If there is no existing tuple, add the key to the list of 
keys for this token
+               //
+               ISharedData existing = getSharedData(apiKey, widgetId, 
contextId, data.getDkey());
+               if (existing == null){
+                       jedis.lpush(context, key);                      
+               } else {
+                       //
+                       // if it already exists, and the instruction is to 
append, prepend the 
+                       // existing value to the new value to set
+                       //
+                       if (append && existing.getDvalue() != null && 
data.getDvalue() != null){
+                               data.setDvalue(existing.getDvalue() + 
data.getDvalue());
+                       }
+               }
+
+               //
+               // Convert the object into JSON for storage
+               //
+               String json = dehydrateData(data);
+               
+               //
+               // Store the preference
+               //
+               jedis.set(key, json);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // OK
+               //
+               return true;
+               
+       }
+
+               
+       @Override
+       public boolean updateSharedData(String apiKey, String widgetId,
+                       String contextId, String name, String value, boolean 
append) {
+               ISharedData data = new DefaultSharedDataImpl(name, value);
+               return this.updateSharedData(apiKey, widgetId, contextId, data, 
append);
+       }
+       
+       
+       ///// Participants API
+
+       @Override
+       public IParticipant[] getParticipants(String apiKey, String widgetId,
+                       String contextId) {
+               //
+               // get the redis context key
+               //
+               String context = this.getContextKey(apiKey, widgetId, 
contextId);
+               
+               //
+               // get a jedis connector
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Get the context list
+               //
+               List<String> keys = jedis.lrange(context, 0, 999);
+               ArrayList<IParticipant> participants = new 
ArrayList<IParticipant>();
+               
+               //
+               // For each item in the list, if its a IParticipant object, get 
+               // it and add it to the array
+               //
+               for (String key: keys){
+                       
+                       //
+                       // Get the IParticipant for each key on the list and 
+                       // add it to the arraylist
+                       //
+                       if (key.startsWith("participant")){
+                       String json = jedis.get(key);
+                       IParticipant item = rehydrateParticipant(json);
+                       participants.add(item);
+                       }
+               }
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // Return the array of ISharedData objects
+               //
+               return participants.toArray(new 
IParticipant[participants.size()]);
+       }
+
+       @Override
+       public boolean addParticipant(String apiKey, String widgetId,
+                       String contextId, String participantId,
+                       String participantDisplayName, String 
participantThumbnailUrl) {
+               return addParticipant(apiKey, widgetId, contextId, 
participantId, participantDisplayName,  participantThumbnailUrl, null);
+       }
+
+       @Override
+       public boolean addParticipant(String apiKey, String widgetId,
+                       String contextId, String participantId,
+                       String participantDisplayName, String 
participantThumbnailUrl,
+                       String role) {
+               IParticipant participant = new 
DefaultParticipantImpl(participantId, participantDisplayName,  
participantThumbnailUrl, role);
+               return addParticipant(apiKey, widgetId, contextId, participant);
+       }
+
+       private boolean addParticipant(String apiKey, String widgetId,
+                       String contextId, IParticipant participant) {
+               //
+               // Check if there is an object to add
+               //
+               if (participant == null) return false;
+               
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // Get the redis key to use for this object
+               //
+               String key = getParticipantKey(apiKey, widgetId, contextId, 
participant.getParticipantId());
+               
+               //
+               // If there is no existing tuple, add the key to the list of 
keys for this token
+               //
+               if (this.getParticipant(apiKey, widgetId, contextId, 
participant.getParticipantId()) == null){
+                       jedis.lpush(this.getContextKey(apiKey, widgetId, 
contextId), key);                      
+               }
+
+               //
+               // Convert the object into JSON for storage
+               //
+               String json = dehydrateParticipant(participant);
+               
+               //
+               // Store the object
+               //
+               jedis.set(key, json);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // OK
+               //
+               return true;
+       }
+
+       @Override
+       public void removeParticipant(String apiKey, String widgetId,
+                       String contextId, IParticipant participant) {
+               removeParticipant(apiKey, widgetId, contextId, 
participant.getParticipantId());
+       }
+
+       @Override
+       public boolean removeParticipant(String apiKey, String widgetId,
+                       String contextId, String participantId) {
+               
+               //
+               // Get a Jedis from the pool
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // get the Redis key for the participant
+               //
+               String key = this.getParticipantKey(apiKey, widgetId, 
contextId, participantId);
+               
+               //
+               // if it doesn't exist, return false
+               //
+               if ( this.getParticipant(apiKey, widgetId, contextId, 
participantId) == null){
+                       return false;
+               }
+                               
+               //
+               // Delete the object
+               //
+               jedis.del(key);
+               
+               //
+               // Remove the key from the context list
+               //
+               String context = this.getContextKey(apiKey, widgetId, 
contextId);
+               jedis.lrem(context, 0, key);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // OK
+               //
+               return true;
+       }
+
+       @Override
+       public IParticipant getParticipant(String apiKey, String widgetId,
+                       String contextId, String participantId) {
+               //
+               // Get the key
+               //
+               String key = this.getParticipantKey(apiKey, widgetId, 
contextId, participantId);
+               
+               //
+               // get a jedis connector
+               //
+               Jedis jedis = pool.getResource();
+               
+               //
+               // get an object from the store and rehydrate it from json
+               //
+               String json = jedis.get(key);
+               IParticipant participant = rehydrateParticipant(json);
+               
+               //
+               // Release Jedis back to the pool
+               //
+               pool.returnResource(jedis);
+               
+               //
+               // Return the object
+               //
+               return participant;
+       }
+
+       @Override
+       public IParticipant getViewer(String apiKey, String widgetId,
+                       String contextId, String viewerId) {
+               return this.getParticipant(apiKey, widgetId, contextId, 
viewerId);
+       }
+
+       @Override
+       public IParticipant getHost(String apiKey, String widgetId, String 
contextId) {
+               IParticipant[] hosts = getHosts(apiKey, widgetId, contextId);
+               if (hosts == null || hosts.length == 0) return null;
+               return hosts[0];
+       }
+
+       @Override
+       public IParticipant[] getHosts(String apiKey, String widgetId,
+                       String contextId) {
+               
+               //
+               // Create a hosts array
+               //
+               ArrayList<IParticipant> hosts = new ArrayList<IParticipant>();
+               
+               //
+               // Iterate over participants and add them if they have a host 
role
+               //
+               for (IParticipant participant: this.getParticipants(apiKey, 
widgetId, contextId)){
+                       if 
(participant.getRole().equals(IParticipant.HOST_ROLE)){
+                               hosts.add(participant);
+                       }
+               }
+               
+               //
+               // Return the array
+               //
+               return hosts.toArray(new IParticipant[hosts.size()]);
+       }
+       
+       ///// Utilities
+
+       private String getContextKey(String apiKey, String widgetId, String 
contextId){
+               return apiKey+"-"+contextId+"-"+widgetId;
+       }
+       
+       private String getDataKey(String apiKey, String widgetId, String 
contextId, String name){
+               return "data::"+getContextKey(apiKey, widgetId, 
contextId)+"::"+name;
+       }
+       
+       private String getParticipantKey(String apiKey, String widgetId, String 
contextId, String participantId){
+               return "participant::"+getContextKey(apiKey, widgetId, 
contextId)+"::"+participantId;
+       }
+       
+       private String dehydrateData(ISharedData data){
+               JSONObject json = new JSONObject();
+               json.put("name", data.getDkey());
+               json.put("value", data.getDvalue());
+               return json.toString();
+       }
+
+       private String dehydrateParticipant(IParticipant participant){
+               JSONObject json = new JSONObject();
+               json.put("id", participant.getParticipantId());
+               json.put("name", participant.getParticipantDisplayName());
+               json.put("thumbnail", participant.getParticipantThumbnailUrl());
+               json.put("role", participant.getRole());
+               return json.toString();
+       }
+       
+       private ISharedData rehydrateData(String input){
+               if (input == null) return null;
+               JSONObject json = new JSONObject(input);
+               DefaultSharedDataImpl data = new 
DefaultSharedDataImpl(json.getString("name"), json.getString("value"));
+               return data;
+       }
+       
+       private IParticipant rehydrateParticipant(String input){
+               if (input == null) return null;
+               JSONObject json = new JSONObject(input);
+               DefaultParticipantImpl participant = new 
DefaultParticipantImpl(json.getString("id"), json.getString("name"), 
json.getString("thumbnail"), json.getString("role"));
+               return participant;
+       }
+}


Reply via email to