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