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