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 CHANNELID_KEY_PREFIX = KEY_PREFIX + "CHANNELID.";
046            private static final String SUBSCRIPTION_KEY_PREFIX = KEY_PREFIX + "SUBSCRIPTION.";
047            private static final String DESTINATION_CLIENTID_KEY_PREFIX = "org.granite.gravity.channel.clientId.";
048            private static final String DESTINATION_SUBSCRIPTIONID_KEY_PREFIX = "org.granite.gravity.channel.subscriptionId.";
049            private static final String DESTINATION_SELECTOR_KEY_PREFIX = KEY_PREFIX + "org.granite.gravity.selector.";
050            
051            private final HttpSession session;
052    
053            private static HttpSession getSession() {
054                    GraniteContext context = GraniteContext.getCurrentInstance();
055                    if (context instanceof HttpGraniteContext)
056                            return ((HttpGraniteContext)context).getSession(false);
057                    return null;
058            }
059            
060            public SessionGraniteDistributedData() {
061                    this(getSession());
062            }
063            
064            public SessionGraniteDistributedData(HttpSession session) {
065                    if (session == null)
066                            throw new NullPointerException("HTTP session cannot be null");
067                    this.session = session;
068            }
069            
070            public Object getCredentials() {
071                    return session.getAttribute(CREDENTIALS_KEY);
072            }
073    
074            public boolean hasCredentials() {
075                    return (getCredentials() != null);
076            }
077    
078            public void setCredentials(Object credentials) {
079                    if (credentials != null)
080                            session.setAttribute(CREDENTIALS_KEY, credentials);
081                    else
082                            removeCredentials();
083            }
084    
085            public void removeCredentials() {
086                    session.removeAttribute(CREDENTIALS_KEY);
087            }
088    
089            public void addChannelId(String channelId) {
090                    if (channelId == null)
091                            throw new NullPointerException("channelId cannot be null");
092                    session.setAttribute(CHANNELID_KEY_PREFIX + channelId, Boolean.TRUE);
093            }
094    
095            public boolean hasChannelId(String channelId) {
096                    if (channelId == null)
097                            return false;
098                    return (session.getAttribute(CHANNELID_KEY_PREFIX + channelId) != null);
099            }
100    
101            public void removeChannelId(String channelId) {
102                    if (channelId == null)
103                            return;
104                    session.removeAttribute(CHANNELID_KEY_PREFIX + channelId);
105                    clearSubscriptions(channelId);
106            }
107    
108            public Set<String> getChannelIds() {
109                    Set<String> channelIds = new HashSet<String>();
110                    for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements(); ) {
111                            String key = e.nextElement();
112                            if (key.startsWith(CHANNELID_KEY_PREFIX))
113                                    channelIds.add(key.substring(CHANNELID_KEY_PREFIX.length()));
114                    }
115                    return channelIds;
116            }
117    
118            public void clearChannelIds() {
119                    Set<String> channelIds = getChannelIds();
120                    for (String channelId : channelIds)
121                            removeChannelId(channelId);
122            }
123    
124            public void addSubcription(String channelId, CommandMessage message) {
125                    if (channelId == null || message == null)
126                            throw new IllegalArgumentException("channelId and message cannot be null");
127                    if (!hasChannelId(channelId))
128                            throw new IllegalArgumentException("Unknown channelId: " + channelId);
129                    if (channelId.indexOf('.') != -1)
130                            throw new IllegalArgumentException("Invalid channelId (should not contain '.' characters): " + channelId);
131                    String subscriptionId = (String)message.getHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER);
132                    if (subscriptionId == null)
133                            throw new IllegalArgumentException("Subscription id cannot be null: " + message);
134                    session.setAttribute(SUBSCRIPTION_KEY_PREFIX + channelId + '.' + subscriptionId, message);
135            }
136    
137            public boolean hasSubcription(String channelId, String subscriptionId) {
138                    if (channelId == null || subscriptionId == null)
139                            return false;
140                    return (session.getAttribute(SUBSCRIPTION_KEY_PREFIX + channelId + '.' + subscriptionId) != null);
141            }
142    
143            public void removeSubcription(String channelId, String subscriptionId) {
144                    if (channelId == null || subscriptionId == null)
145                            return;
146                    session.removeAttribute(SUBSCRIPTION_KEY_PREFIX + channelId + '.' + subscriptionId);
147            }
148    
149            public List<CommandMessage> getSubscriptions(String channelId) {
150                    if (channelId == null)
151                            return Collections.emptyList();
152                    String channelSubscriptionKeyPrefix = SUBSCRIPTION_KEY_PREFIX + channelId + '.';
153                    List<CommandMessage> subscriptions = new ArrayList<CommandMessage>();
154                    for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements(); ) {
155                            String key = e.nextElement();
156                            if (key.startsWith(channelSubscriptionKeyPrefix)) {
157                                    CommandMessage subscription = (CommandMessage)session.getAttribute(key);
158                                    subscriptions.add(subscription);
159                            }
160                    }
161                    return subscriptions;
162            }
163    
164            public void clearSubscriptions(String channelId) {
165                    if (channelId == null)
166                            return;
167                    String channelSubscriptionKeyPrefix = SUBSCRIPTION_KEY_PREFIX + channelId + '.';
168                    for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements(); ) {
169                            String key = e.nextElement();
170                            if (key.startsWith(channelSubscriptionKeyPrefix))
171                                    session.removeAttribute(key);
172                    }
173            }
174            
175            
176            public String getDestinationClientId(String destination) {
177                    return (String)session.getAttribute(DESTINATION_CLIENTID_KEY_PREFIX + destination);
178            }
179            
180            public void setDestinationClientId(String destination, String clientId) {
181                    session.setAttribute(DESTINATION_CLIENTID_KEY_PREFIX + destination, clientId);
182            }
183            
184            public String getDestinationSubscriptionId(String destination) {
185                    return (String)session.getAttribute(DESTINATION_SUBSCRIPTIONID_KEY_PREFIX + destination);
186            }
187            
188            public void setDestinationSubscriptionId(String destination, String subscriptionId) {
189                    session.setAttribute(DESTINATION_SUBSCRIPTIONID_KEY_PREFIX + destination, subscriptionId);
190            }
191            
192            public String getDestinationSelector(String destination) {
193                    return (String)session.getAttribute(DESTINATION_SELECTOR_KEY_PREFIX + destination);
194            }
195            
196            public void setDestinationSelector(String destination, String selector) {
197                    session.setAttribute(DESTINATION_SELECTOR_KEY_PREFIX + destination, selector);
198            }
199    }