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