View Javadoc

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 }