1 package org.lsst.ccs.bus;
2
3
4 //import org.apache.log4j.Logger;
5
6
7 import org.lsst.ccs.utilities.logging.Logger;
8
9 /**
10 * this is to distinguish the transport layer for message from their Application layer.
11 * This code I do not understand is copied from JMSMessagingFactory with extraction
12 * of what should be relevant to the application layer!!
13 * <P>
14 * SPECS TO BE IMPLEMENTED:
15 * <BR>
16 * each Subsystems should have its own Application layer (an instance for each subsystem).
17 * <BR>
18 * this instance deals with linking command/response and data that links subsystem name with
19 * routing data for the transport layer
20 * <BR>
21 * the fact that the transport layer is a singleton should be transparent
22 * (for instance in Jgroups this is not the case! each subssystem can have its own Address on the net!)
23 * </BR>
24 * </BR>
25 * So this class should be dumped and MessagingFactroy changed
26 * the messaging should be a protected member of subsystem
27 * </P>
28 * @author bamade
29 */
30 public class MessagingApplicationLayer {
31 Logger logger = Logger.getLogger("org.lsst.ccs.bus.layer") ;
32 ///////// COPIED FROM JMS
33 // Thread local pattern assumes reply will be send on same thread
34 // will not handle deferred executions of commands.
35 // thread local context is only set when receiving a message
36 // JMS specific : ThreadLocal<String> localCorrelID = new ThreadLocal<String>();
37 // JMS sepcificThreadLocal<String> localReplyTo = new ThreadLocal<String>();// changed Destination to String
38 ThreadLocal<String> localOrigin = new ThreadLocal<String>();
39 ThreadLocal<Command> localCommand = new ThreadLocal<Command>();
40 String token = java.util.UUID.randomUUID().toString(); // for arbitrator
41
42 // should be set to "MAIN" for the main control module that holds all locks
43 // initially
44 // TODO (at the moment default value for subsystem allows any command)
45 public String getToken() {
46 return token;
47 }
48
49 volatile boolean replyRequested = true ;
50 public boolean isReplyRequested() {
51 //return localReplyTo.get() != null;
52 //TODO: ??????
53 return replyRequested ;
54 }
55
56
57 public void noAutoReply() {
58 //localReplyTo.set(null);
59 }
60 /////////////////////////////////////// COPIED FROM JMS
61
62 // COMMAND INITIATING SIDE
63
64 /**
65 * the command id tagged with a token, an origin, and a correlation
66 * @param cmd
67 * @return
68 */
69 public Command commandForSending(Command cmd) {
70 cmd.setKey(token);
71 cmd.setOrigin(MessagingFactory.getInstance().getSubsystemName());
72 // @TODO: is this relevant? not sure at all!! probalby a bug in JMSMessagingFactory
73 /*.
74 if (cmd.getCorrelId() == null) {
75 cmd.setCorrelId(localCorrelID.get());
76 }
77 */
78 if (cmd.getCorrelId() == null) {
79 // let's generate one
80 cmd.setCorrelId(java.util.UUID.randomUUID().toString());
81 }
82 return cmd ;
83 }
84
85
86 /**
87 * if you are not the one who initiated the command, ditch it!
88 * it means that CommandReply should have a destination !
89 * is this a transport or an application layer problem?
90 * @param reply
91 * @return null if this is not for you!
92 */
93 public CommandAckOrReply receivingReply(CommandAckOrReply reply) {
94 // does not deal with threadLocal things! (or so I think!)
95 // ALAS it does!
96 String local = MessagingFactory.getInstance().getSubsystemName();
97 if(local == null) {
98 logger.warn("TODO: modify subsystem name knowledge (BUG)");
99 return reply ;
100 }
101 Command command =reply.getOriginalCommand();
102 if (command == null) {
103 logger.warn("null command in reply");
104 return reply ;
105 }
106 if(local.equals(command.getOrigin())) {
107 return reply ;
108 }
109 // @TODO : check!
110 logger.warn("!!!!!! LOST REPLY!");
111 return reply ;
112 }
113 // END INITIATIVE
114
115 // INVOLVED SIDE : BEWARE OF THREAD ISSUES receiving a command and replying should be handled by
116 // a single Thread
117 // these methods SHOULD BE CALLED inside that Thread (nor before dispatching to other threads!)
118 public Command receivingCommand(Command command) {
119 localOrigin.set(command.getOrigin());
120 localCommand.set(command);
121 return command ;
122 }
123 /**
124 * this method shoudl be modified to us a transport layer information to be returned
125 *
126 * @param reply
127 * @return
128 */
129 public CommandAckOrReply replyForSending(CommandAckOrReply reply) {
130 // String dest = localReplyTo.get();
131 String destSystem = localOrigin.get();
132 logger.info("REPLY destination:" + destSystem);
133
134
135 reply.setOriginalCommand(localCommand.get());
136 //@TODO: CHANGE THAT!!!!!
137 //localCommand.set(null);
138 //localOrigin.set(null);
139 if (reply.getCorrelId() == null) {
140 // WAS : reply.setCorrelId(localCorrelID.get());
141 Command originalCommand = reply.getOriginalCommand() ;
142 if(originalCommand != null) {
143 reply.setCorrelId(reply.getOriginalCommand().getCorrelId());
144 } else {
145 reply.setCorrelId("no command correlation");
146 }
147 }
148 reply.setOrigin(MessagingFactory.getInstance().getSubsystemName());
149 return reply ;
150 }
151
152 /// END COMMANDS
153
154 public Status statusForSending(Status status) {
155 return status ;
156 }
157
158 public LogEvent logForSending(LogEvent log) {
159 return log ;
160 }
161
162
163 public Status receivingStatus(Status status) {
164 return status ;
165 }
166
167 public LogEvent receivingLog(LogEvent log) {
168 return log ;
169 }
170
171 }