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 }