Clover coverage report -
Coverage timestamp: Sa Jul 7 2007 09:11:40 CEST
file stats: LOC: 191   Methods: 5
NCLOC: 90   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
JMSBroadcastingListener.java 0% 0% 0% 0%
coverage
 1    /*
 2    * Copyright (c) 2002-2003 by OpenSymphony
 3    * All rights reserved.
 4    */
 5    package com.opensymphony.oscache.plugins.clustersupport;
 6   
 7    import com.opensymphony.oscache.base.Cache;
 8    import com.opensymphony.oscache.base.Config;
 9    import com.opensymphony.oscache.base.FinalizationException;
 10    import com.opensymphony.oscache.base.InitializationException;
 11   
 12    import org.apache.commons.logging.Log;
 13    import org.apache.commons.logging.LogFactory;
 14   
 15    import javax.jms.*;
 16   
 17    import javax.naming.InitialContext;
 18    import javax.naming.NamingException;
 19   
 20    /**
 21    * A JMS based clustering implementation. This implementation is independent of the
 22    * JMS provider and uses non-persistent messages on a publish subscribe protocol.
 23    *
 24    * @author <a href="mailto:motoras@linuxmail.org">Romulus Pasca</a>
 25    */
 26    public class JMSBroadcastingListener extends AbstractBroadcastingListener {
 27   
 28    private final static Log log = LogFactory.getLog(JMSBroadcastingListener.class);
 29   
 30    /**
 31    *The JMS connection used
 32    */
 33    private Connection connection;
 34   
 35    /**
 36    * Th object used to publish new messages
 37    */
 38    private MessageProducer messagePublisher;
 39   
 40    /**
 41    * The current JMS session
 42    */
 43    private Session publisherSession;
 44   
 45    /**
 46    * The name of this cluster. Used to identify the sender of a message.
 47    */
 48    private String clusterNode;
 49   
 50    /**
 51    * <p>Called by the cache administrator class when a cache is instantiated.</p>
 52    * <p>The JMS broadcasting implementation requires the following configuration
 53    * properties to be specified in <code>oscache.properties</code>:
 54    * <ul>
 55    * <li><b>cache.cluster.jms.topic.factory</b> - The JMS connection factory to use</li>
 56    * <li><b>cache.cluster.jms.topic.name</b> - The JMS topic name</li>
 57    * <li><b>cache.cluster.jms.node.name</b> - The name of this node in the cluster. This
 58    * should be unique for each node.</li>
 59    * Please refer to the clustering documentation for further details on configuring
 60    * the JMS clustered caching.</p>
 61    *
 62    * @param cache the cache instance that this listener is attached to.
 63    *
 64    * @throws com.opensymphony.oscache.base.InitializationException thrown when there was a
 65    * problem initializing the listener. The cache administrator will log this error and
 66    * disable the listener.
 67    */
 68  0 public void initialize(Cache cache, Config config) throws InitializationException {
 69  0 super.initialize(cache, config);
 70   
 71    // Get the name of this node
 72  0 clusterNode = config.getProperty("cache.cluster.jms.node.name");
 73   
 74  0 String topic = config.getProperty("cache.cluster.jms.topic.name");
 75  0 String topicFactory = config.getProperty("cache.cluster.jms.topic.factory");
 76   
 77  0 if (log.isInfoEnabled()) {
 78  0 log.info("Starting JMS clustering (node name=" + clusterNode + ", topic=" + topic + ", topic factory=" + topicFactory + ")");
 79    }
 80   
 81  0 try {
 82    // Make sure you have specified the necessary JNDI properties (usually in
 83    // a jndi.properties resource file, or as system properties)
 84  0 InitialContext jndi = getInitialContext();
 85   
 86    // Look up a JMS connection factory
 87  0 ConnectionFactory connectionFactory = (ConnectionFactory) jndi.lookup(topicFactory);
 88   
 89    // Create a JMS connection
 90  0 connection = connectionFactory.createConnection();
 91   
 92    // Create session objects
 93  0 publisherSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 94   
 95  0 Session subSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 96   
 97    // Look up the JMS topic
 98  0 Topic chatTopic = (Topic) jndi.lookup(topic);
 99   
 100    // Create the publisher and subscriber
 101  0 messagePublisher = publisherSession.createProducer(chatTopic);
 102   
 103  0 MessageConsumer messageConsumer = subSession.createConsumer(chatTopic);
 104   
 105    // Set the message listener
 106  0 messageConsumer.setMessageListener(new MessageListener() {
 107  0 public void onMessage(Message message) {
 108  0 try {
 109    //check the message type
 110  0 ObjectMessage objectMessage = null;
 111   
 112  0 if (!(message instanceof ObjectMessage)) {
 113  0 log.error("Cannot handle message of type (class=" + message.getClass().getName() + "). Notification ignored.");
 114  0 return;
 115    }
 116   
 117  0 objectMessage = (ObjectMessage) message;
 118   
 119    //check the message content
 120  0 if (!(objectMessage.getObject() instanceof ClusterNotification)) {
 121  0 log.error("An unknown cluster notification message received (class=" + objectMessage.getObject().getClass().getName() + "). Notification ignored.");
 122  0 return;
 123    }
 124   
 125  0 if (log.isDebugEnabled()) {
 126  0 log.debug(objectMessage.getObject());
 127    }
 128   
 129    // This prevents the notification sent by this node from being handled by itself
 130  0 if (!objectMessage.getStringProperty("nodeName").equals(clusterNode)) {
 131    //now handle the message
 132  0 ClusterNotification notification = (ClusterNotification) objectMessage.getObject();
 133  0 handleClusterNotification(notification);
 134    }
 135    } catch (JMSException jmsEx) {
 136  0 log.error("Cannot handle cluster Notification", jmsEx);
 137    }
 138    }
 139    });
 140   
 141    // Start the JMS connection; allows messages to be delivered
 142  0 connection.start();
 143    } catch (Exception e) {
 144  0 throw new InitializationException("Initialization of the JMSBroadcastingListener failed: " + e);
 145    }
 146    }
 147   
 148    /**
 149    * Called by the cache administrator class when a cache is destroyed.
 150    *
 151    * @throws com.opensymphony.oscache.base.FinalizationException thrown when there was a problem finalizing the
 152    * listener. The cache administrator will catch and log this error.
 153    */
 154  0 public void finialize() throws FinalizationException {
 155  0 try {
 156  0 if (log.isInfoEnabled()) {
 157  0 log.info("Shutting down JMS clustering...");
 158    }
 159   
 160  0 connection.close();
 161   
 162  0 if (log.isInfoEnabled()) {
 163  0 log.info("JMS clustering shutdown complete.");
 164    }
 165    } catch (JMSException e) {
 166  0 log.warn("A problem was encountered when closing the JMS connection", e);
 167    }
 168    }
 169   
 170  0 protected void sendNotification(ClusterNotification message) {
 171  0 try {
 172  0 ObjectMessage objectMessage = publisherSession.createObjectMessage();
 173  0 objectMessage.setObject(message);
 174   
 175    //sign the message, with the name of this node
 176  0 objectMessage.setStringProperty("nodeName", clusterNode);
 177  0 messagePublisher.send(objectMessage);
 178    } catch (JMSException e) {
 179  0 log.error("Cannot send notification " + message, e);
 180    }
 181    }
 182   
 183    /**
 184    * @return creates a context for performing naming operations.
 185    * @throws NamingException if a naming exception is encountered
 186    */
 187  0 protected InitialContext getInitialContext() throws NamingException {
 188  0 return new InitialContext();
 189    }
 190   
 191    }