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     */
022    package org.granite.tide.data;
023    
024    import java.util.Map;
025    import java.util.Map.Entry;
026    
027    import org.granite.clustering.DistributedData;
028    import org.granite.clustering.DistributedDataFactory;
029    import org.granite.context.GraniteContext;
030    import org.granite.gravity.Channel;
031    import org.granite.gravity.Gravity;
032    import org.granite.gravity.GravityManager;
033    import org.granite.logging.Logger;
034    import org.granite.messaging.webapp.ServletGraniteContext;
035    
036    import flex.messaging.messages.AsyncMessage;
037    import flex.messaging.messages.CommandMessage;
038    import flex.messaging.messages.ErrorMessage;
039    import 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     */
050    public 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                    gravity = GravityManager.getGravity(((ServletGraniteContext)graniteContext).getServletContext());
084    
085                            if (gravity == null) {
086                                    log.debug("Gravity not defined, data dispatch disabled");
087                                    return;
088                            }
089                            
090                            this.gravity = gravity;
091                            this.sessionId = DataDispatcher.SERVER_DISPATCHER_GDS_SESSION_ID;
092                    }
093                    
094                    enabled = true;
095            }
096            
097            
098            @Override
099            protected void changeDataSelector(String dataSelector) {
100                    DistributedDataFactory distributedDataFactory = GraniteContext.getCurrentInstance().getGraniteConfig().getDistributedDataFactory();             
101                    DistributedData gdd = distributedDataFactory.getInstance();
102                    if (gdd != null) {
103                            String clientId = gdd.getDestinationClientId(topicName);
104                            String subscriptionId = gdd.getDestinationSubscriptionId(topicName);
105                            
106                            if (clientId != null) {
107                                    CommandMessage message = new CommandMessage();
108                                    message.setClientId(clientId);
109                                    message.setHeader(AsyncMessage.DESTINATION_CLIENT_ID_HEADER, subscriptionId);
110                                    message.setHeader(AsyncMessage.SUBTOPIC_HEADER, TIDE_DATA_SUBTOPIC);
111                                    message.setDestination(topicName);
112                                    message.setOperation(CommandMessage.SUBSCRIBE_OPERATION);
113                                    
114                                    message.setHeader(CommandMessage.SELECTOR_HEADER, dataSelector);
115                                    
116                                    gravity.handleMessage(null, message, true);
117                                    
118                                    log.debug("Topic %s data selector changed: %s", topicName, dataSelector);
119                            }
120                    }
121            }
122            
123            @Override
124            public void publishUpdate(Map<String, String> params, Object body) {
125                    AsyncMessage message = new AsyncMessage();
126                    message.setDestination(topicName);
127                    for (Entry<String, String> hh : params.entrySet())
128                            message.setHeader(hh.getKey(), hh.getValue());
129                    message.setBody(body);
130                    
131                    Message resultMessage = null;
132                    if (clientId != null) {
133                            Channel channel = gravity.getChannel(null, clientId);
134                            message.setClientId(clientId);
135                            resultMessage = gravity.publishMessage(channel, message);
136                    }
137                    else
138                            resultMessage = gravity.publishMessage(message);
139                    
140                    if (resultMessage instanceof ErrorMessage)
141                            log.error("Could not dispatch data update on topic %s, message %s", topicName, resultMessage.toString());
142                    else
143                            log.debug("Data message dispatched on topic %s", topicName);
144            }
145    }