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