51d5fd8190514b4cfce1dcae7f3343eb8345aa86
[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 ) { req.set_complete(); }
158                                 new Logger().debug( " * Request completed: " + tt, Logger.INFO );
159                                 return;
160                         }
161
162                         default: { break; } 
163                 }
164
165         }
166
167         // throw any exceptions received from the server
168         if( domain_object_payload instanceof oilsException ) {
169                 throw new oils_ex_session( domain_object_payload.getStatus() );
170         }
171
172         new Logger().debug( "Message Layer passing up:\n" + domain_object_payload.toString(), Logger.DEBUG );
173
174         Application.handler( session, domain_object_payload, tt );
175
176 }
177
178 /** Utility method for cleaning up a session.  Sets state to disconnected.
179   * resets the remoted_id, pushes the current app_request onto the resend
180   * queue. Logs a message.
181   */
182 Message.reset_session = function( session, thread_trace, message ) {
183         session.set_state( AppSession.DISCONNECTED );
184         session.reset_remote();
185         var req = session.get_request( thread_trace );
186         if( req && !req.complete ) { session.push_resend( req ); }
187         new Logger().debug( " * " + message + " : " + thread_trace, Logger.INFO );
188 }
189
190
191 /** Pushes all incoming messages onto the session message queue. **/
192 Application.handler = function( session, domain_object_payload, thread_trace ) {
193
194         new Logger().debug( "Application Pushing onto queue: " 
195                         + thread_trace + "\n" + domain_object_payload.toString(), Logger.DEBUG );
196
197         session.push_queue( domain_object_payload, thread_trace );
198 }
199
200
201         
202
203