001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.gravity.gae; 022 023import org.granite.config.GraniteConfig; 024import org.granite.config.flex.ServicesConfig; 025import org.granite.gravity.Channel; 026import org.granite.gravity.ChannelFactory; 027import org.granite.gravity.DefaultGravity; 028import org.granite.gravity.GravityConfig; 029import org.granite.gravity.Subscription; 030import org.granite.util.UUIDUtil; 031 032import com.google.appengine.api.memcache.Expiration; 033import com.google.appengine.api.memcache.MemcacheService; 034import com.google.appengine.api.memcache.MemcacheServiceFactory; 035 036import flex.messaging.messages.Message; 037 038/** 039 * @author William DRAI 040 * @author Franck WOLFF 041 */ 042public class GAEGravity extends DefaultGravity { 043 044 /////////////////////////////////////////////////////////////////////////// 045 // Fields. 046 047 static final String CHANNEL_PREFIX = "org.granite.gravity.gae.channel."; 048 049 private static MemcacheService gaeCache = MemcacheServiceFactory.getMemcacheService(); 050 051 /////////////////////////////////////////////////////////////////////////// 052 // Constructor. 053 054 public GAEGravity(GravityConfig gravityConfig, ServicesConfig servicesConfig, GraniteConfig graniteConfig) { 055 super(gravityConfig, servicesConfig, graniteConfig); 056 } 057 058 059 /////////////////////////////////////////////////////////////////////////// 060 // Channel's operations. 061 062 @Override 063 protected <C extends Channel> C createChannel(ChannelFactory<C> channelFactory, String channelId) { 064 C channel = null; 065 if (channelId != null) { 066 channel = getChannel(channelFactory, channelId); 067 if (channel != null) 068 return channel; 069 } 070 071 channel = channelFactory.newChannel(UUIDUtil.randomUUID(), null); 072 Expiration expiration = Expiration.byDeltaMillis((int)getGravityConfig().getChannelIdleTimeoutMillis()); 073 gaeCache.put(CHANNEL_PREFIX + channel.getId(), channel, expiration); 074 gaeCache.put(GAEChannel.MSG_COUNT_PREFIX + channel.getId(), 0L, expiration); 075 return channel; 076 } 077 078 @SuppressWarnings("unchecked") 079 @Override 080 public <C extends Channel> C getChannel(ChannelFactory<C> channelFactory, String channelId) { 081 if (channelId == null) 082 return null; 083 084 return (C)gaeCache.get(CHANNEL_PREFIX + channelId); 085 } 086 087 088 @Override 089 public Channel removeChannel(String channelId) { 090 if (channelId == null) 091 return null; 092 093 Channel channel = (Channel)gaeCache.get(CHANNEL_PREFIX + channelId); 094 if (channel != null) { 095 for (Subscription subscription : channel.getSubscriptions()) { 096 Message message = subscription.getUnsubscribeMessage(); 097 handleMessage(channel.getFactory(), message, true); 098 } 099 100 channel.destroy(); 101 gaeCache.delete(CHANNEL_PREFIX + channelId); 102 gaeCache.delete(GAEChannel.MSG_COUNT_PREFIX + channelId); 103 } 104 105 return channel; 106 } 107 108 @Override 109 public boolean access(String channelId) { 110 return true; 111 } 112 113 114 @Override 115 public void internalStart() { 116 // Avoid starting thread pool 117 } 118 119 120 @Override 121 protected void postManage(Channel channel) { 122 Expiration expiration = Expiration.byDeltaMillis((int)getGravityConfig().getChannelIdleTimeoutMillis()); 123 gaeCache.put(CHANNEL_PREFIX + channel.getId(), channel, expiration); 124 } 125}