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.tide.data;
022    
023    import java.util.Map;
024    import java.util.Map.Entry;
025    
026    import javax.servlet.http.HttpSession;
027    
028    import org.granite.clustering.GraniteDistributedData;
029    import org.granite.clustering.GraniteDistributedDataFactory;
030    import org.granite.context.GraniteContext;
031    import org.granite.gravity.Channel;
032    import org.granite.gravity.Gravity;
033    import org.granite.gravity.GravityManager;
034    import org.granite.logging.Logger;
035    import org.granite.messaging.webapp.HttpGraniteContext;
036    
037    import flex.messaging.messages.AsyncMessage;
038    import flex.messaging.messages.CommandMessage;
039    import flex.messaging.messages.ErrorMessage;
040    import flex.messaging.messages.Message;
041    
042    
043    /**
044     *  Default implementation for data update dispatchers using the Gravity API to dispatch updates.
045     * 
046     *  @see DataDispatcher
047     *  @see DataContext
048     * 
049     *  @author William Drai
050     */
051    public class DefaultDataDispatcher extends AbstractDataDispatcher {
052        
053        private static final Logger log = Logger.getLogger(DefaultDataDispatcher.class);
054    
055        
056        private Gravity gravity = null;
057        private String clientId = null;
058        private String subscriptionId = null;
059        
060        
061            public DefaultDataDispatcher(Gravity gravity, String topicName, Class<? extends DataTopicParams> dataTopicParamsClass) {
062                    super(topicName, dataTopicParamsClass);
063                    
064                    GraniteContext graniteContext = GraniteContext.getCurrentInstance();
065                    if (gravity == null && graniteContext == null)
066                            return;
067                    
068                    if (graniteContext instanceof HttpGraniteContext) {
069                            this.gravity = GravityManager.getGravity(((HttpGraniteContext)graniteContext).getServletContext());
070                            
071                            HttpSession session = ((HttpGraniteContext)graniteContext).getSession(false);
072                            if (this.gravity == null || session == null) {
073                                    log.debug("Gravity not found or HTTP session not found, data dispatch disabled");
074                                    return;
075                            }
076                            sessionId = session.getId();
077                            GraniteDistributedData gdd = GraniteDistributedDataFactory.getInstance();
078                            
079                            clientId = gdd.getDestinationClientId(topicName);
080                            if (clientId == null) {
081                                    log.debug("Gravity channel clientId not defined, data dispatch disabled");
082                                    return;
083                            }
084                            subscriptionId = gdd.getDestinationSubscriptionId(topicName);
085                            if (subscriptionId == null) {
086                                    log.debug("Gravity channel subscriptionId not defined, data dispatch disabled");
087                                    return;
088                            }
089                    }
090                    else {
091                            if (gravity == null) {
092                                    log.debug("Gravity not defined, data dispatch disabled");
093                                    return;
094                            }
095                            
096                            this.gravity = gravity;
097                            this.sessionId = DataDispatcher.SERVER_DISPATCHER_GDS_SESSION_ID;
098                    }
099                    
100                    enabled = true;
101            }
102            
103            
104            @Override
105            protected void changeDataSelector(String dataSelector) {
106                    HttpSession session = ((HttpGraniteContext)GraniteContext.getCurrentInstance()).getSession(false);
107                    
108                    if (session != null) {
109                            GraniteDistributedData gdd = GraniteDistributedDataFactory.getInstance();
110                            String clientId = gdd.getDestinationClientId(topicName);
111                            String subscriptionId = gdd.getDestinationSubscriptionId(topicName);
112                            
113                            if (clientId != null) {
114                                    CommandMessage message = new CommandMessage();
115                                    message.setClientId(clientId);
116                                    message.setHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER, subscriptionId);
117                                    message.setHeader(AsyncMessage.SUBTOPIC_HEADER, TIDE_DATA_SUBTOPIC);
118                                    message.setDestination(topicName);
119                                    message.setOperation(CommandMessage.SUBSCRIBE_OPERATION);
120                                    
121                                    message.setHeader(CommandMessage.SELECTOR_HEADER, dataSelector);
122                                    
123                                    gravity.handleMessage(message, true);
124                                    
125                                    log.debug("Topic %s data selector changed: %s", topicName, dataSelector);
126                            }
127                    }
128            }
129            
130            @Override
131            public void publishUpdate(Map<String, String> params, Object body) {
132                    Channel channel = gravity.getChannel(clientId);
133                    AsyncMessage message = new AsyncMessage();
134                    message.setClientId(clientId);
135                    message.setDestination(topicName);
136                    for (Entry<String, String> hh : params.entrySet())
137                            message.setHeader(hh.getKey(), hh.getValue());
138                    message.setBody(body);
139                    
140                    Message resultMessage = gravity.publishMessage(channel, message);
141                    if (resultMessage instanceof ErrorMessage)
142                            log.error("Could not dispatch data update on topic %s, message %s", topicName, resultMessage.toString());
143                    else
144                            log.debug("Data message dispatched on topic %s", topicName);
145            }
146    }