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 */ 022package org.granite.tide.data; 023 024import java.io.Serializable; 025import java.util.Map; 026import java.util.Map.Entry; 027 028import javax.jms.Connection; 029import javax.jms.JMSException; 030import javax.jms.MessageProducer; 031import javax.jms.ObjectMessage; 032import javax.jms.Session; 033import javax.jms.Topic; 034import javax.jms.TopicConnectionFactory; 035import javax.naming.InitialContext; 036import javax.naming.NamingException; 037import javax.servlet.http.HttpSession; 038 039import org.granite.context.GraniteContext; 040import org.granite.gravity.adapters.JMSClient; 041import org.granite.logging.Logger; 042import 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 */ 052public 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}