]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/javascript/opensrf_msg_stack.js
added support for multi-threaded client interactions. much like the java lib, each...
[OpenSRF.git] / src / javascript / opensrf_msg_stack.js
1 // -----------------------------------------------------------------------------
2 // Message stack code.
3 // -----------------------------------------------------------------------------
4
5
6
7 // -----------------------------------------------------------------------------
8 // These just have to be defined for the 'static' methods to work
9 // -----------------------------------------------------------------------------
10 function Transport() {}
11 function Message() {}
12 function Application() {}
13
14 /** Transport handler.  
15   * Takes a transport_message as parameter
16   * Parses the incoming message data and builds one or more oilsMessage objects
17   * from the XML.  Each message is passed in turn to the Message.handler
18   * method.
19   */
20 Transport.handler = function( msg ) {
21
22         if( msg.is_error_msg ) {
23                 throw new oils_ex_session( "Receved error message from jabber server for recipient: " + msg.get_sender() );
24                 return;
25         }
26
27         var remote_id   = msg.get_sender();
28         var session_id = msg.get_thread();
29         var body                        = msg.get_body();
30
31         var session             = AppSession.find_session( session_id );
32
33         if( ! session ) {
34                 new Logger().debug( "No AppSession found with id: " + session_id );
35                 return;
36         }
37
38         session.set_remote_id( remote_id );
39
40         var nodelist; // oilsMessage nodes
41
42
43         // -----------------------------------------------------------------------------
44         // Parse the incoming XML
45         // -----------------------------------------------------------------------------
46         try {
47
48                 var doc = new DOMParser().parseFromString( body, "text/xml" );
49                 nodelist = doc.documentElement.getElementsByTagName( "oils:domainObject" );
50
51                 if( ! nodelist || nodelist.length < 1 ) {
52                         nodelist = doc.documentElement.getElementsByTagName( "domainObject" );
53                         if( ! nodelist || nodelist.length < 1 ) { throw 1; }
54                 }
55
56         } catch( E ) {
57
58                 var str = "Error parsing incoming message document";
59
60                 if( E ) { throw new oils_ex_dom( str + "\n" + E.message + "\n" + body ); 
61                 } else { throw new oils_ex_dom( str + "\n" + body ); }
62
63         }
64         
65         // -----------------------------------------------------------------------------
66         // Pass the messages up the chain.
67         // -----------------------------------------------------------------------------
68         try {
69
70                 var i = 0;
71                 var node = nodelist.item(i); // a single oilsMessage
72
73                 while( node != null ) {
74
75                         if( node.getAttribute("name") != "oilsMessage" ) {
76                                 node = nodelist.item(++i);
77                                 continue;
78                         }
79                                 
80                         var oils_msg = new oilsMessage().replaceNode( node );  
81
82
83                         // -----------------------------------------------------------------------------
84                         // this is really inefficient compared to the above line of code,
85                         // however, this resolves some namespace oddities in DOMParser - 
86                         // namely, DOMParser puts dummy namesapaces in "a0" when, I'm assuming, it 
87                         // can't find the definition for the namesapace included.
88                         // -----------------------------------------------------------------------------
89                         //      var oils_msg = oilsMessage.newFromXML( new XMLSerializer().serializeToString( node ) );
90
91                         new Logger().transport( "Transport passing up:\n" + oils_msg.toString(true), Logger.INFO );
92
93                         // Pass the message off to the message layer
94                         Message.handler( session, oils_msg );
95                         node = nodelist.item(++i);
96                 }
97
98         } catch( E ) {
99
100                 var str = "Processing Error";
101
102                 if( E ) { throw new oils_ex_session( str + "\n" + E.message + "\n" + body ); } 
103                 else { throw new oils_ex_session( str + "\n" + body ); }
104         }
105 }
106
107 /** Checks to see what type of message has arrived.  If it is a 'STATUS' message,
108   * the appropriate transport layer actions are taken.  Otherwise (RESULT), the
109   * message is passed to the Application.handler method.
110   */
111 Message.handler = function( session, msg ) {
112
113         var msg_type                                    = msg.getType();
114         var domain_object_payload       = msg.getPayload();
115         var tt                                                  = msg.getThreadTrace();
116
117         var code = domain_object_payload.getStatusCode();
118
119         new Logger().debug( "Message.handler received " + msg_type + " from " +
120                         session.get_remote_id() + " with thread_trace " + tt + " and status " + code, Logger.INFO );
121         new Logger().debug( "Message.handler received:\n" + domain_object_payload.toString(), Logger.DEBUG );
122
123         if( msg_type == oilsMessage.STATUS ) {
124
125                 switch( code ) {
126
127                         case  oilsResponse.STATUS_OK + "": {
128                                 session.set_state( AppSession.CONNECTED );
129                                 new Logger().debug( " * Connected Successfully: " + tt, Logger.INFO );
130                                 return;
131                         }
132
133                         case oilsResponse.STATUS_TIMEOUT + "": {
134                                 return Message.reset_session( session, tt, "Disconnected because of timeout" );
135                         }
136
137                         case oilsResponse.STATUS_REDIRECTED + "": {
138                                 return Message.reset_session( session, tt, "Disconnected because of redirect" );
139                         }
140
141                         case oilsResponse.STATUS_EXPFAILED + "": {
142                                 return Message.reset_session( session, tt, "Disconnected because of mangled session" );
143                         }
144
145                         case oilsResponse.STATUS_NOTALLOWED + "": {
146                                 new Logger().debug( "Method Not Allowed", Logger.ERROR );
147                                 session.destroy();
148                                 break; // we want the exception to be thrown below
149                         }
150
151                         case oilsResponse.STATUS_CONTINUE +"": {
152                                 return;
153                         }
154
155                         case oilsResponse.STATUS_COMPLETE + "": {
156                                 var req = session.get_request(tt);
157                                 if( req ) { 
158                                         req.set_complete(); 
159                                         new Logger().debug( " * Request completed: " + tt, Logger.INFO );
160                                 }
161                                 return;
162                         }
163
164                         default: { break; } 
165                 }
166
167         }
168
169         // throw any exceptions received from the server
170         if( domain_object_payload instanceof oilsException ) {
171                 throw new oils_ex_session( domain_object_payload.getStatus() );
172         }
173
174         new Logger().debug( "Message Layer passing up:\n" + domain_object_payload.toString(), Logger.DEBUG );
175
176         Application.handler( session, domain_object_payload, tt );
177
178 }
179
180 /** Utility method for cleaning up a session.  Sets state to disconnected.
181   * resets the remoted_id, pushes the current app_request onto the resend
182   * queue. Logs a message.
183   */
184 Message.reset_session = function( session, thread_trace, message ) {
185         session.set_state( AppSession.DISCONNECTED );
186         session.reset_remote();
187         var req = session.get_request( thread_trace );
188         if( req && !req.complete() ) { session.push_resend( req ); }
189         new Logger().debug( " * " + message + " : " + thread_trace, Logger.INFO );
190 }
191
192
193 /** Pushes all incoming messages onto the session message queue. **/
194 Application.handler = function( session, domain_object_payload, thread_trace ) {
195
196         new Logger().debug( "Application Pushing onto queue: " 
197                         + thread_trace + "\n" + domain_object_payload.toString(), Logger.DEBUG );
198
199         session.push_queue( domain_object_payload, thread_trace );
200 }
201
202
203         
204
205