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.io.Serializable;
025 import java.util.Map;
026 import java.util.Map.Entry;
027
028 import javax.jms.Connection;
029 import javax.jms.JMSException;
030 import javax.jms.MessageProducer;
031 import javax.jms.ObjectMessage;
032 import javax.jms.Session;
033 import javax.jms.Topic;
034 import javax.jms.TopicConnectionFactory;
035 import javax.naming.InitialContext;
036 import javax.naming.NamingException;
037 import javax.servlet.http.HttpSession;
038
039 import org.granite.context.GraniteContext;
040 import org.granite.gravity.adapters.JMSClient;
041 import org.granite.logging.Logger;
042 import org.granite.messaging.webapp.ServletGraniteContext;
043
044 /**
045 * Implementation for data update dispatchers using JMS to dispatch updates.
046 *
047 * @see DataDispatcher
048 * @see DataContext
049 *
050 * @author William Drai
051 */
052 public class JMSDataDispatcher extends AbstractDataDispatcher {
053
054 private static final Logger log = Logger.getLogger(JMSDataDispatcher.class);
055
056
057 private boolean transacted = false;
058 private TopicConnectionFactory connectionFactory = null;
059 private Topic topic;
060 private JMSClient jmsClient = null;
061
062
063 public JMSDataDispatcher(String topicName, boolean transacted, Class<? extends DataTopicParams> dataTopicParamsClass) {
064 super(topicName, dataTopicParamsClass);
065
066 this.transacted = transacted;
067
068 GraniteContext graniteContext = GraniteContext.getCurrentInstance();
069 if (graniteContext instanceof ServletGraniteContext) {
070 HttpSession session = ((ServletGraniteContext)graniteContext).getSession(false);
071 if (session == null) {
072 log.debug("Gravity not found or HTTP session not found, data dispatch disabled");
073 return;
074 }
075 sessionId = session.getId();
076
077 jmsClient = (JMSClient)((ServletGraniteContext)graniteContext).getSessionMap().get(JMSClient.JMSCLIENT_KEY_PREFIX + topicName);
078 }
079 else {
080 // Server initiated dispatcher
081 this.sessionId = SERVER_DISPATCHER_GDS_SESSION_ID;
082
083 try {
084 InitialContext ic = new InitialContext();
085 this.connectionFactory = (TopicConnectionFactory)ic.lookup("java:comp/env/tide/ConnectionFactory");
086 this.topic = (Topic)ic.lookup("java:comp/env/tide/topic/" + topicName);
087 }
088 catch (NamingException e) {
089 log.warn(e, "Could not retrieve ConnectionFactory and Topic in JNDI for topic %s", topicName);
090 return;
091 }
092 }
093
094 enabled = true;
095 }
096
097
098 @Override
099 protected void changeDataSelector(String dataSelector) {
100 if (jmsClient != null) {
101 try {
102 jmsClient.subscribe(dataSelector, topicName, TIDE_DATA_SUBTOPIC);
103 log.debug("JMS Topic %s data selector changed: %s", topicName, dataSelector);
104 }
105 catch (Exception e) {
106 log.error(e, "Could not change JMS Topic %s data selector: %s", topicName);
107 }
108 }
109 }
110
111 @Override
112 public void publishUpdate(Map<String, String> params, Object body) {
113 if (jmsClient != null) {
114 try {
115 jmsClient.send(params, body, 0L);
116 }
117 catch (Exception e) {
118 log.error("Could not dispatch data update on topic %s using internal JMS client, message %s", topicName, body.toString());
119 }
120 }
121 else if (enabled) {
122 try {
123 Connection jmsConnection = connectionFactory.createConnection();
124 Session jmsSession = jmsConnection.createSession(transacted, Session.AUTO_ACKNOWLEDGE);
125 MessageProducer jmsProducer = jmsSession.createProducer(topic);
126 ObjectMessage jmsMessage = jmsSession.createObjectMessage((Serializable)body);
127 for (Entry<String, String> hh : params.entrySet())
128 jmsMessage.setStringProperty(hh.getKey(), hh.getValue());
129
130 jmsProducer.send(jmsMessage);
131 log.debug("Data message dispatched on JMS topic %s", topicName);
132 }
133 catch (JMSException e) {
134 log.error("Could not dispatch data update on topic %s, message %s", topicName, body.toString());
135 }
136 }
137 }
138 }