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