Clover coverage report - Coverage timestamp: Sa Jul 7 2007 09:11:40 CEST FRAMES NO FRAMES |
file stats: | LOC: | 191 |  | Methods: | 5
| NCLOC: | 90 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
JMSBroadcastingListener.java | 0% | 0% | 0% | 0% |

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 |  | }