1 package org.lsst.ccs.bus.jms;
2
3 import org.lsst.ccs.bus.*;
4 import org.lsst.ccs.utilities.logging.Logger;
5
6 import javax.jms.Destination;
7 import javax.jms.JMSException;
8 import javax.jms.MessageConsumer;
9 import javax.jms.MessageListener;
10 import javax.jms.MessageProducer;
11 import javax.jms.ObjectMessage;
12 import javax.jms.Queue;
13 import javax.jms.Session;
14 import java.util.Map;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.ExecutorService;
17 import java.util.concurrent.Executors;
18
19
20
21
22
23
24
25 public class JMSMessagingFactory extends MessagingFactory {
26
27
28
29
30 ThreadLocal<String> localCorrelID = new ThreadLocal<String>();
31 ThreadLocal<Destination> localReplyTo = new ThreadLocal<Destination>();
32 ThreadLocal<String> localOrigin = new ThreadLocal<String>();
33 ThreadLocal<Command> localCommand = new ThreadLocal<Command>();
34 String token = java.util.UUID.randomUUID().toString();
35
36
37
38
39 @Override
40 public String getToken() {
41 return token;
42 }
43
44 protected static Logger log = Logger
45 .getLogger("org.lsst.ccs.bus.jms.JMSMessagingFactory");
46
47 @Override
48 public void addCommandListener(final CommandListener l) {
49 addCommandListener(l, null);
50 }
51
52
53
54 ExecutorService exec = Executors.newFixedThreadPool(5);
55
56 class MessageHandler implements Runnable {
57
58 public MessageHandler(ObjectMessage msg, CommandListener l) {
59 this.msg = msg;
60 this.l = l;
61 }
62
63 ObjectMessage msg;
64 CommandListener l;
65
66 public void run() {
67 Object payload;
68 try {
69 payload = ((ObjectMessage) msg).getObject();
70
71 if (payload instanceof Command) {
72 localCorrelID.set(msg.getJMSCorrelationID());
73 localReplyTo.set(msg.getJMSReplyTo());
74 localOrigin.set(((Command) payload).getOrigin());
75 localCommand.set((Command) payload);
76 l.onCommand((Command) payload);
77 } else if (payload instanceof CommandReply) {
78 localCorrelID.set(msg.getJMSCorrelationID());
79 localReplyTo.set(null);
80 localOrigin.set(null);
81 l.onReply((CommandReply) payload);
82 } else if (payload instanceof CommandAck) {
83 localCorrelID.set(msg.getJMSCorrelationID());
84 localReplyTo.set(null);
85 localOrigin.set(null);
86 l.onAck((CommandAck) payload);
87 } else {
88 log.warn("Message payload type "
89 + payload.getClass().getName() + " not handled "
90 + payload);
91 }
92 } catch (JMSException e) {
93 log.error("Problem receiving message, class not handled?", e);
94 }
95
96 }
97 }
98
99
100
101
102 Map<CommandListener, MessageConsumer> commandListenerMap = new ConcurrentHashMap<CommandListener, MessageConsumer>();
103
104 @Override
105 public void addCommandListener(final CommandListener l, String selector) {
106 log.debug("adding command listener, selector='" + selector + "'");
107 Session session = TopicSessionFactory.getSessionFactory()
108 .getTopicSession();
109 MessageConsumer sub = (selector == null) ? TopicSessionFactory
110 .getSessionFactory().getCommandSubscriber(session)
111 : TopicSessionFactory.getSessionFactory().getCommandSubscriber(
112 session, selector);
113 try {
114 MessageListener ml = new MessageListener() {
115
116 public void onMessage(javax.jms.Message msg) {
117 if (msg instanceof ObjectMessage) {
118 log.debug("MessageListener got jms message on command");
119
120 MessageHandler mh = new MessageHandler(
121 (ObjectMessage) msg, l);
122 exec.execute(mh);
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148 } else {
149 log.warn("Message type " + msg.getClass().getName()
150 + " not handled " + msg);
151
152 }
153 }
154 };
155 commandListenerMap.put(l, sub);
156 sub.setMessageListener(ml);
157 commandMessageListener = ml;
158 } catch (JMSException e) {
159 throw new RuntimeException(e);
160 }
161 }
162
163 @Override
164 public void removeCommandListener(CommandListener l) {
165 MessageConsumer sub = commandListenerMap.get(l);
166
167
168 if (sub == null)
169 return;
170 try {
171 sub.setMessageListener(null);
172 sub.close();
173 } catch (JMSException e) {
174 throw new RuntimeException(e);
175 }
176 commandListenerMap.remove(l);
177 }
178
179 MessageListener commandMessageListener;
180
181
182
183
184
185
186
187
188 @Override
189 public void addStatusListener(final StatusListens l) {
190 addStatusListener(l, null);
191 }
192
193 Map<StatusListens, MessageConsumer> statusListenerMap = new ConcurrentHashMap<StatusListens, MessageConsumer>();
194
195 @Override
196 public void addStatusListener(final StatusListens l, String selector) {
197 log.debug("adding status listener, selector='" + selector + "'");
198 Session session = TopicSessionFactory.getSessionFactory()
199 .getTopicSession();
200 MessageConsumer sub = TopicSessionFactory.getSessionFactory()
201 .getStatusSubscriber(session, selector);
202 MessageListener ml = new MessageListener() {
203
204 BusApplicationLayer.ForwarderToStatus forwarder =
205 new BusApplicationLayer("", null).new ForwarderToStatus(l);
206
207 public void onMessage(javax.jms.Message msg) {
208 if (msg instanceof ObjectMessage) {
209 log.debug("MessageListener got jms message on status");
210 Object payload;
211 try {
212 payload = ((ObjectMessage) msg).getObject();
213 } catch (JMSException e) {
214 log.error(
215 "Got Object Message, could not deserialize: missing class?",
216 e);
217 return;
218
219 }
220 if (payload instanceof Status) {
221 forwarder.update((BusMessage)payload);
222 } else {
223 log.warn("Message payload type "
224 + payload.getClass().getName()
225 + " not handled " + payload);
226
227 }
228 } else {
229 log.warn("Message type " + msg.getClass().getName()
230 + " not handled " + msg);
231
232 }
233 }
234 };
235 try {
236 statusListenerMap.put(l, sub);
237 sub.setMessageListener(ml);
238 } catch (JMSException e) {
239 log.error(e);
240 throw new RuntimeException(e);
241 }
242 }
243
244 @Override
245 public void removeStatusListener(StatusListens l) {
246 MessageConsumer sub = statusListenerMap.get(l);
247
248
249 if (sub == null)
250 return;
251 try {
252 sub.setMessageListener(null);
253 sub.close();
254 } catch (JMSException e) {
255 throw new RuntimeException(e);
256 }
257 statusListenerMap.remove(l);
258 }
259
260 @Override
261 public void addLogListener(LogListener l) {
262 addLogListener(l, null);
263 }
264
265 Map<LogListener, MessageConsumer> logListenerMap = new ConcurrentHashMap<LogListener, MessageConsumer>();
266
267 @Override
268 public void addLogListener(final LogListener l, String selector) {
269 log.debug("adding log listener, selector='" + selector + "'");
270 Session session = TopicSessionFactory.getSessionFactory()
271 .getTopicSession();
272 MessageConsumer sub = TopicSessionFactory.getSessionFactory()
273 .getLogSubscriber(session, selector);
274 MessageListener ml = new MessageListener() {
275
276 public void onMessage(javax.jms.Message msg) {
277 if (msg instanceof ObjectMessage) {
278 log.debug("MessageListener got jms message on log");
279 Object payload;
280 try {
281 payload = ((ObjectMessage) msg).getObject();
282 } catch (JMSException e) {
283 throw new RuntimeException(e);
284 }
285 if (payload instanceof LogEvent) {
286 l.onLog((LogEvent) payload);
287 } else {
288 log.warn("Message payload type "
289 + payload.getClass().getName()
290 + " not handled " + payload);
291
292 }
293 } else {
294 log.warn("Message type " + msg.getClass().getName()
295 + " not handled " + msg);
296
297 }
298 }
299 };
300 try {
301 logListenerMap.put(l, sub);
302 sub.setMessageListener(ml);
303 } catch (JMSException e) {
304 log.error(e);
305 throw new RuntimeException(e);
306 }
307
308 }
309
310 @Override
311 public void removeLogListener(LogListener l) {
312 MessageConsumer sub = logListenerMap.get(l);
313
314
315 if (sub == null)
316 return;
317 try {
318 sub.setMessageListener(null);
319 sub.close();
320 } catch (JMSException e) {
321 throw new RuntimeException(e);
322 }
323 logListenerMap.remove(l);
324 }
325
326 @Override
327 public void sendCommand(Command cmd) {
328 cmd.setKey(token);
329
330 if (null == cmd.getOrigin()) {
331 cmd.setOrigin(MessagingFactory.getInstance().getSubsystemName());
332 }
333 if (cmd.getCorrelId() == null) {
334 cmd.setCorrelId(localCorrelID.get());
335 }
336 if (cmd.getCorrelId() == null) {
337
338 cmd.setCorrelId(java.util.UUID.randomUUID().toString());
339 }
340 Session sess = TopicSessionFactory.getSessionFactory()
341 .getTopicSession();
342 MessageProducer send = TopicSessionFactory.getSessionFactory()
343 .getCommandPublisher(sess);
344 ObjectMessage m;
345
346 try {
347 m = sess.createObjectMessage();
348 m.setObject(cmd);
349 m.setJMSType(cmd.getMessageType());
350 m.setStringProperty("destination", cmd.getDestination());
351 m.setJMSPriority(convertToJMSPriority(cmd.getPriorityLevel()));
352 if (cmd.getCorrelId() != null) {
353 m.setJMSCorrelationID(cmd.getCorrelId());
354 }
355 log.debug("sending command " + cmd);
356
357 sendMessage(m, sess, send);
358 sess.close();
359 } catch (JMSException e) {
360 log.error(e);
361 throw new RuntimeException(e);
362 }
363 }
364
365 public static int convertToJMSPriority(PriorityLevel level) {
366 switch (level) {
367 case DEBUG:
368 return 0;
369 case INFO:
370 return 4;
371 case OPERATION:
372 return 5;
373 case CRITICAL:
374 return 9;
375 }
376 return 4;
377 }
378
379 @Override
380 public void sendStatus(Status s) {
381
382 if (null == s.getOrigin()) {
383 s.setOrigin(MessagingFactory.getInstance().getSubsystemName());
384 }
385
386 Session sess = TopicSessionFactory.getSessionFactory()
387 .getTopicSession();
388 MessageProducer send = TopicSessionFactory.getSessionFactory()
389 .getStatusPublisher(sess);
390 ObjectMessage m;
391 try {
392 m = sess.createObjectMessage();
393 m.setObject(s);
394 m.setJMSType(s.getMessageType());
395 m.setJMSTimestamp(System.currentTimeMillis());
396
397 m.setJMSPriority(convertToJMSPriority(s.getPriorityLevel()));
398
399
400
401
402 m.setStringProperty("destination", "*");
403 log.debug("sending status " + s);
404 sendMessage(m, sess, send);
405 sess.close();
406 } catch (JMSException e) {
407 log.error(e);
408 throw new RuntimeException(e);
409 }
410 }
411
412 @Override
413 public void sendLogEvent(LogEvent evt) {
414 Session sess = TopicSessionFactory.getSessionFactory()
415 .getTopicSession();
416 MessageProducer send = TopicSessionFactory.getSessionFactory()
417 .getLogPublisher(sess);
418 ObjectMessage m;
419 try {
420 m = sess.createObjectMessage();
421 m.setObject(evt);
422 m.setJMSType(evt.getMessageType());
423 m.setStringProperty("destination", "*");
424 m.setJMSPriority(convertToJMSPriority(evt.getPriorityLevel()));
425 log.debug("sending log " + evt);
426
427 sendMessage(m, sess, send);
428 sess.close();
429 } catch (JMSException e) {
430 log.error(e);
431 throw new RuntimeException(e);
432 }
433
434 }
435
436 protected void sendMessage(ObjectMessage m, Session sess,
437 MessageProducer sender) {
438 try {
439 if (m.getJMSCorrelationID() == null) {
440 m.setJMSCorrelationID(localCorrelID.get());
441 }
442 m.setJMSMessageID("0");
443 m.setJMSPriority(4);
444
445
446
447 m.setJMSReplyTo(TopicSessionFactory.getSessionFactory()
448 .getCommandTopic());
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469 m.setJMSTimestamp(System.currentTimeMillis());
470
471 sender.send(m);
472 sender.close();
473 } catch (JMSException e) {
474 log.error("Error sending message", e);
475 throw new RuntimeException(e);
476 } finally {
477 try {
478 sess.close();
479 } catch (JMSException e) {
480 log.error("Error closing JMS session", e);
481 throw new RuntimeException(e);
482 }
483 }
484
485 }
486
487 @Override
488 public boolean isReplyRequested() {
489 return localReplyTo.get() != null;
490 }
491
492 @Override
493 public void noAutoReply() {
494 localReplyTo.set(null);
495 }
496
497 @Override
498 public void reply(CommandAckOrReply reply) {
499 Destination dest = localReplyTo.get();
500 String destSystem = localOrigin.get();
501
502 if (reply.getCorrelId() == null) {
503 reply.setCorrelId(localCorrelID.get());
504 }
505
506 reply.setOriginalCommand(localCommand.get());
507
508 if (null == reply.getOrigin()) {
509 reply.setOrigin(MessagingFactory.getInstance().getSubsystemName());
510 }
511
512 log.debug("sending reply " + reply + " to " + dest + "[" + destSystem
513 + "]");
514
515
516
517
518
519
520 if (dest instanceof Queue) {
521 Session sess = QueueSessionFactory.getSessionFactory()
522 .getQueueSession();
523 MessageProducer sender = QueueSessionFactory.getSessionFactory()
524 .getCommandReplySender(sess, dest);
525 ObjectMessage m;
526 try {
527 m = sess.createObjectMessage();
528 m.setObject(reply);
529 if (reply instanceof CommandReply)
530 m.setJMSType("lsst.commandreply");
531 else
532 m.setJMSType("lsst.commandack");
533 m.setStringProperty("destination", destSystem);
534 m.setJMSCorrelationID(reply.getCorrelId());
535 sender.send(m);
536 sender.close();
537 sess.close();
538 } catch (JMSException e) {
539 log.error(e);
540 }
541 } else {
542 Session sess = TopicSessionFactory.getSessionFactory()
543 .getTopicSession();
544 MessageProducer sender = TopicSessionFactory.getSessionFactory()
545 .getCommandReplyPublisher(sess, dest);
546 ObjectMessage m;
547 try {
548 m = sess.createObjectMessage();
549 m.setObject(reply);
550 if (reply instanceof CommandReply)
551 m.setJMSType("lsst.commandreply");
552 else
553 m.setJMSType("lsst.commandack");
554 m.setStringProperty("destination", destSystem);
555 m.setJMSCorrelationID(reply.getCorrelId());
556 sender.send(m);
557 sender.close();
558 sess.close();
559 } catch (JMSException e) {
560 log.error(e);
561 }
562
563 }
564
565 }
566 @Override
567 public void addMembershipListener(BusMembershipListener l) {
568 throw new UnsupportedOperationException("Unsupported pending re-implementation: LSSTCCS-149");
569 }
570
571 @Override
572 public void removeMembershipListener(BusMembershipListener l) {
573 throw new UnsupportedOperationException("Unsupported pending re-implementation: LSSTCCS-149");
574 }
575
576 }