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
021 package org.granite.clustering;
022
023 import java.util.ArrayList;
024 import java.util.Collections;
025 import java.util.Enumeration;
026 import java.util.HashSet;
027 import java.util.List;
028 import java.util.Set;
029
030 import javax.servlet.http.HttpSession;
031
032 import org.granite.context.GraniteContext;
033 import org.granite.messaging.webapp.HttpGraniteContext;
034
035 import flex.messaging.messages.AsyncMessage;
036 import flex.messaging.messages.CommandMessage;
037
038 /**
039 * @author Franck WOLFF
040 */
041 public class SessionGraniteDistributedData implements GraniteDistributedData {
042
043 private static final String KEY_PREFIX = "__GDD__";
044 private static final String CREDENTIALS_KEY = KEY_PREFIX + "CREDENTIALS";
045 private static final String CREDENTIALS_CHARSET_KEY = KEY_PREFIX + "CREDENTIALS_CHARSET";
046 private static final String CHANNELID_KEY_PREFIX = KEY_PREFIX + "CHANNELID.";
047 private static final String SUBSCRIPTION_KEY_PREFIX = KEY_PREFIX + "SUBSCRIPTION.";
048 private static final String DESTINATION_CLIENTID_KEY_PREFIX = "org.granite.gravity.channel.clientId.";
049 private static final String DESTINATION_SUBSCRIPTIONID_KEY_PREFIX = "org.granite.gravity.channel.subscriptionId.";
050 private static final String DESTINATION_SELECTOR_KEY_PREFIX = KEY_PREFIX + "org.granite.gravity.selector.";
051
052 private final HttpSession session;
053
054 private static HttpSession getSession() {
055 GraniteContext context = GraniteContext.getCurrentInstance();
056 if (context instanceof HttpGraniteContext)
057 return ((HttpGraniteContext)context).getSession(false);
058 return null;
059 }
060
061 public SessionGraniteDistributedData() {
062 this(getSession());
063 }
064
065 public SessionGraniteDistributedData(HttpSession session) {
066 if (session == null)
067 throw new NullPointerException("HTTP session cannot be null");
068 this.session = session;
069 }
070
071 public Object getCredentials() {
072 return session.getAttribute(CREDENTIALS_KEY);
073 }
074
075 public boolean hasCredentials() {
076 return (getCredentials() != null);
077 }
078
079 public void setCredentials(Object credentials) {
080 if (credentials != null)
081 session.setAttribute(CREDENTIALS_KEY, credentials);
082 else
083 removeCredentials();
084 }
085
086 public void removeCredentials() {
087 session.removeAttribute(CREDENTIALS_KEY);
088 }
089
090 public String getCredentialsCharset() {
091 return (String)session.getAttribute(CREDENTIALS_CHARSET_KEY);
092 }
093
094 public boolean hasCredentialsCharset() {
095 return (getCredentialsCharset() != null);
096 }
097
098 public void setCredentialsCharset(String credentialsCharset) {
099 if (credentialsCharset != null)
100 session.setAttribute(CREDENTIALS_CHARSET_KEY, credentialsCharset);
101 else
102 removeCredentialsCharset();
103 }
104
105 public void removeCredentialsCharset() {
106 session.removeAttribute(CREDENTIALS_CHARSET_KEY);
107 }
108
109 public void addChannelId(String channelId) {
110 if (channelId == null)
111 throw new NullPointerException("channelId cannot be null");
112 session.setAttribute(CHANNELID_KEY_PREFIX + channelId, Boolean.TRUE);
113 }
114
115 public boolean hasChannelId(String channelId) {
116 if (channelId == null)
117 return false;
118 return (session.getAttribute(CHANNELID_KEY_PREFIX + channelId) != null);
119 }
120
121 public void removeChannelId(String channelId) {
122 if (channelId == null)
123 return;
124 session.removeAttribute(CHANNELID_KEY_PREFIX + channelId);
125 clearSubscriptions(channelId);
126 }
127
128 public Set<String> getChannelIds() {
129 Set<String> channelIds = new HashSet<String>();
130 for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements(); ) {
131 String key = e.nextElement();
132 if (key.startsWith(CHANNELID_KEY_PREFIX))
133 channelIds.add(key.substring(CHANNELID_KEY_PREFIX.length()));
134 }
135 return channelIds;
136 }
137
138 public void clearChannelIds() {
139 Set<String> channelIds = getChannelIds();
140 for (String channelId : channelIds)
141 removeChannelId(channelId);
142 }
143
144 public void addSubcription(String channelId, CommandMessage message) {
145 if (channelId == null || message == null)
146 throw new IllegalArgumentException("channelId and message cannot be null");
147 if (!hasChannelId(channelId))
148 throw new IllegalArgumentException("Unknown channelId: " + channelId);
149 if (channelId.indexOf('.') != -1)
150 throw new IllegalArgumentException("Invalid channelId (should not contain '.' characters): " + channelId);
151 String subscriptionId = (String)message.getHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER);
152 if (subscriptionId == null)
153 throw new IllegalArgumentException("Subscription id cannot be null: " + message);
154 session.setAttribute(SUBSCRIPTION_KEY_PREFIX + channelId + '.' + subscriptionId, message);
155 }
156
157 public boolean hasSubcription(String channelId, String subscriptionId) {
158 if (channelId == null || subscriptionId == null)
159 return false;
160 return (session.getAttribute(SUBSCRIPTION_KEY_PREFIX + channelId + '.' + subscriptionId) != null);
161 }
162
163 public void removeSubcription(String channelId, String subscriptionId) {
164 if (channelId == null || subscriptionId == null)
165 return;
166 session.removeAttribute(SUBSCRIPTION_KEY_PREFIX + channelId + '.' + subscriptionId);
167 }
168
169 public List<CommandMessage> getSubscriptions(String channelId) {
170 if (channelId == null)
171 return Collections.emptyList();
172 String channelSubscriptionKeyPrefix = SUBSCRIPTION_KEY_PREFIX + channelId + '.';
173 List<CommandMessage> subscriptions = new ArrayList<CommandMessage>();
174 for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements(); ) {
175 String key = e.nextElement();
176 if (key.startsWith(channelSubscriptionKeyPrefix)) {
177 CommandMessage subscription = (CommandMessage)session.getAttribute(key);
178 subscriptions.add(subscription);
179 }
180 }
181 return subscriptions;
182 }
183
184 public void clearSubscriptions(String channelId) {
185 if (channelId == null)
186 return;
187 String channelSubscriptionKeyPrefix = SUBSCRIPTION_KEY_PREFIX + channelId + '.';
188 for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements(); ) {
189 String key = e.nextElement();
190 if (key.startsWith(channelSubscriptionKeyPrefix))
191 session.removeAttribute(key);
192 }
193 }
194
195
196 public String getDestinationClientId(String destination) {
197 return (String)session.getAttribute(DESTINATION_CLIENTID_KEY_PREFIX + destination);
198 }
199
200 public void setDestinationClientId(String destination, String clientId) {
201 session.setAttribute(DESTINATION_CLIENTID_KEY_PREFIX + destination, clientId);
202 }
203
204 public String getDestinationSubscriptionId(String destination) {
205 return (String)session.getAttribute(DESTINATION_SUBSCRIPTIONID_KEY_PREFIX + destination);
206 }
207
208 public void setDestinationSubscriptionId(String destination, String subscriptionId) {
209 session.setAttribute(DESTINATION_SUBSCRIPTIONID_KEY_PREFIX + destination, subscriptionId);
210 }
211
212 public String getDestinationSelector(String destination) {
213 return (String)session.getAttribute(DESTINATION_SELECTOR_KEY_PREFIX + destination);
214 }
215
216 public void setDestinationSelector(String destination, String selector) {
217 session.setAttribute(DESTINATION_SELECTOR_KEY_PREFIX + destination, selector);
218 }
219 }