1 var Ozone = Ozone || {};
  2 Ozone.util = Ozone.util || {};
  3 
  4 
  5 /**
  6  * @class
  7  * @private
  8  *
  9  * @description
 10  * Object used to talk to the cross domain and locally.  If the server is local,
 11  * then AJAX will be used.  If the server is remote, then we must use a
 12  * hack to get around Same Origin Policy and make the call cross domain.
 13  *
 14  * @requires util.js
 15  */
 16 Ozone.util.Transport = {
 17     version: Ozone.version.owfversion + Ozone.version.preference
 18 };
 19 
 20 
 21 /**
 22  * @private
 23  *
 24  * @params  cfg.url               -  url of the request
 25  *          cfg.method            -  HTTP verb (only POST or GET, use _method = PUT or DELETE with a POST )
 26  *          cfg.onSuccess         -  callback function to capture the success result
 27  *          cfg.onFailure         -  callback to execute if there is an error
 28  *          cfg.content           -  optional content to send with the request, ie {value: 'x', _method: 'PUT'}
 29  *          cfg.async			  -  optional (default is true, asynchronous send, only applies to Ajax call)
 30  *          cfg.handleAs          - text or json
 31  *          cfg.autoSendVersion   -  true to send owf version to the server, false don't send (defaults to true)
 32  *          cfg.ignoredErrorCodes -  optional array of http error codes to ignore (if these happen onSucess will be called)
 33  *          cfg.forceXdomain      -  optional flag to force xdomain ajax call using dojo window.name
 34  *
 35  *  @returns void, use callbacks
 36  *
 37  *  Static method.  Must use 2 callbacks since javascript is asyncronous
 38  *  we have to wait for the response.
 39  *
 40  *  This implementation uses the dojox.windowName hack for a remote server,
 41   * but could be replaced with something else like JSONP if desired
 42  */
 43 Ozone.util.Transport.send = function(cfg) {
 44     if (Ozone.log) {
 45         Ozone.log.getDefaultLogger().debug('Transport Send', cfg.url, cfg.method, cfg.content);
 46     }
 47 
 48     var defaultFailure = function(err) {
 49         // If error is an HTML page, just use body
 50         if (err == undefined || err == null) err = "";
 51         var start = err.indexOf("<body");
 52         if (start > -1) {
 53             // start at the end of the body tag
 54             start = err.indexOf(">", start) + 1;
 55             var stop = err.indexOf("</body>", start);
 56 
 57             if (stop > -1) err = err.substring(start, stop);
 58             else err = err.substring(start);
 59         }
 60 
 61         if (!Ozone.Msg)
 62             Ozone.util.ErrorDlg.show(err,200,50);
 63         else
 64             Ozone.Msg.alert('Server Error',err,null,this,{
 65                 cls: "owfAlert"
 66             });
 67     };
 68 
 69     // create an onFailure method if one doesn't exist
 70     if (!cfg.onFailure) {
 71         cfg.onFailure = function(err){
 72             defaultFailure(err);
 73         };
 74     }
 75 
 76     var methodToUse = cfg.method;
 77     var hasBody = false;
 78     if (methodToUse == "PUT" || methodToUse == "DELETE")
 79     {
 80         methodToUse = "POST";
 81     }
 82 
 83     if (methodToUse == "POST") {
 84         hasBody = true;
 85     }
 86 
 87     if(cfg.content == null) {
 88         cfg.content = {};
 89     }
 90 
 91     //autoSendVersion to server default behavior is true
 92     if (!(cfg.autoSendVersion === false)) {
 93         //add version property to send to the server
 94         cfg.content.version = Ozone.util.Transport.version;
 95     }
 96 
 97     // Convert state JSON object to string
 98     if (cfg.content.state) {
 99         cfg.content.state = Ozone.util.toString(cfg.content.state);
100     }
101 
102     // Convert defaultSettings JSON object to string
103     if (cfg.content.defaultSettings) {
104         cfg.content.defaultSettings = Ozone.util.toString(cfg.content.defaultSettings);
105     }
106 
107     var  content = cfg.content;
108 
109     var handleAs = 'json';
110     if (cfg.handleAs != null) {
111         handleAs = cfg.handleAs;
112     }
113 
114     // Use AJAX if we can
115     if (Ozone.util.isUrlLocal(cfg.url) && !cfg.forceXdomain) {
116         return owfdojo.xhr(methodToUse.toUpperCase(), {
117             url: cfg.url,
118             content: cfg.content,
119             preventCache: true,
120             sync: cfg.async == false? true : false, //defaults to false (not synchronous)
121             timeout : cfg.timeout ? cfg.timeout : 0,
122             headers: {
123                 "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
124             },
125             load: function(response, ioArgs) {
126                 if (Ozone.log) {
127                     Ozone.log.getDefaultLogger().debug('Transport AJAX Return', response);
128                 }
129                 if (handleAs == 'json') {
130                     try {
131                         var json = Ozone.util.parseJson(response);
132                         cfg.onSuccess(json);
133                     } catch(e) {
134                         cfg.onFailure(e.name + " : " + e.message);
135                     }
136                 }
137                 else {
138                     cfg.onSuccess(response);
139                 }
140             },
141             error: function(response, ioArgs) {
142                 if (response.dojoType=='cancel') { return; }
143                 // FF2 kills all AJAX requests when you refresh. When this happens, it sets the status code to 0
144                 if (response.status != 0 ){
145                     if (cfg.ignoredErrorCodes != null && cfg.ignoredErrorCodes.length > 0 && owfdojo.indexOf(cfg.ignoredErrorCodes,response.status) > -1){
146                         cfg.onSuccess({});
147                     }
148                     else {
149                         cfg.onFailure(response.responseText, response.status);
150                     }
151                 }
152             }
153         }, hasBody);
154     } else {
155         // Use window.name transport
156         try {
157             var methodToUse = cfg.method;
158             if (methodToUse == "PUT" || methodToUse == "DELETE")
159             {
160                 methodToUse = "POST";
161             }
162             var deferred = owfdojox.io.windowName.send(methodToUse.toUpperCase(), {
163                 url: cfg.url,
164                 content: content,
165                 preventCache: true,
166                 timeout: cfg.timeout ? cfg.timeout : 20000,
167                 load:
168                 function(result) {
169                     try {
170                         // OWF-2750 - handle timeout errors which are already JSON objects
171                         var json = null;
172                         if (result && typeof(result) === 'string') {
173                            json = Ozone.util.parseJson(result);
174                         }
175                         else {
176                            json = result;
177                         }
178 
179                         // OWF-2750 - detect a timeout error and return its message
180                         if (json && json.message && json.message == 'Timeout') {
181                            return cfg.onFailure('Error: Request timed out');
182                         }
183 
184                         if (json.status === 200) {
185                             if (Ozone.log) {
186                                 Ozone.log.getDefaultLogger().debug('Transport AJAX Return', json.data);
187                             }
188                             if (handleAs == 'json') {
189                                 cfg.onSuccess(json.data);
190                             }
191                             else {
192                                 cfg.onSuccess(result);
193                             }
194                         } else if (json.status === 500 || json.status === 401) {
195                             cfg.onFailure(json.data);
196                         }
197                         //if it is an error code we ignore than call onSuccess with empty data
198                         else if (cfg.ignoredErrorCodes != null && cfg.ignoredErrorCodes.length > 0 && owfdojo.indexOf(cfg.ignoredErrorCodes,json.status) > -1){
199                             cfg.onSuccess({});
200                         }
201                         else {
202                             cfg.onFailure(json.data,json.status);
203                         }
204                         return json;
205                     }
206                     catch(e2) {
207                         cfg.onFailure(e2.name + " : " + e2.message);
208                     }
209                 },
210                 error:
211                 function(result){
212                     if (result.dojoType=='cancel') { return; }
213                     if (result instanceof Error){
214                         cfg.onFailure(result.name + " : " + result.message);
215                     }
216                     else{
217                         cfg.onFailure(result);
218                     }
219                 }
220             });
221             return deferred;
222         }
223         catch(e){
224             cfg.onFailure(e.name + " : " + e.message);
225         }
226     }
227 	
228 };
229 /**
230  * @private
231  *
232  * @params  cfg.url              -  url of the request
233  *          cfg.method           -  HTTP verb (only POST or GET, use _method = PUT or DELETE with a POST )
234  *          cfg.content          -  optional content to send with the request, ie {value: 'x', _method: 'PUT'}
235  *          cfg.async			 -  optional (default is true, asynchronous send, only applies to Ajax call)          
236  *
237  *  @returns void
238  *
239  *  Static method.  No callbacks are passed in, so you will not get a response.  Useful for example in
240  *                  in 'beforeunload' when the the asyncronous callbacks are guaranteed to have the same
241  *                  javascript in the dom when they are firted
242  *
243  *
244  *  This implementation uses the dojox.windowName hack for a remote server,
245   * but could be replaced with something else like JSONP if desired
246  */
247 Ozone.util.Transport.sendAndForget = function(cfg) {
248     var cfg = cfg;
249 
250     if (Ozone.log) {
251         Ozone.log.getDefaultLogger().debug('Transport SendAndForget', cfg.url, cfg.method, cfg.content);
252     }
253 
254     var methodToUse = cfg.method;
255     if (methodToUse == "PUT" || methodToUse == "DELETE")
256     {
257         methodToUse = "POST";
258     }
259 	
260     var hasBody = false;
261     if (methodToUse == "POST") {
262         hasBody = true;
263     }
264 	
265     if(cfg.content == null) {
266         cfg.content = {};
267     }
268 
269     //autoSendVersion to server default behavior is true
270     if (cfg.autoSendVersion === false) {
271         //add version property to send to the server
272         cfg.content.version = Ozone.util.Transport.version;
273     }
274 
275     // Convert state JSON object to string
276     if (cfg.content.state) {
277         cfg.content.state = Ozone.util.toString(cfg.content.state);
278     }
279 
280     var content = null;
281     if (methodToUse == "GET") {
282         content = owfdojo.objectToQuery(cfg.content);
283     }
284     else {
285         content = cfg.content;
286     }
287 
288     // Use AJAX if we can
289     if (Ozone.util.isUrlLocal(cfg.url)) {
290         owfdojo.xhr(methodToUse.toUpperCase(), {
291             url: cfg.url,
292             content: cfg.content,
293             preventCache: true,
294             sync:  cfg.async == false? false : true //defaults to true
295         }, hasBody);
296     } else {
297         // Use window.name transport
298         try {
299             var methodToUse = cfg.method;
300             if (methodToUse == "PUT" || methodToUse == "DELETE")
301             {
302                 methodToUse = "POST";
303             }
304             var deferred = owfdojox.io.windowName.send(methodToUse.toUpperCase(), {
305                 url: cfg.url,
306                 content: content,
307                 preventCache: true
308             });
309         } catch(e) {
310             if (!Ozone.Msg)
311                 Ozone.util.ErrorDlg.show(Ozone.util.ErrorMessageString.sendAndForget,e.name + " : " + e.message,200,50);
312             else
313                 Ozone.Msg.alert(Ozone.util.ErrorMessageString.sendAndForget,e.name + " : " + e.message);
314         }
315     }
316 };
317 
318 
319 /**
320  * @private
321  *
322  *  @params  cfg.urls              -  Array of urls to try
323  *           cfg.method           -  HTTP verb (only POST or GET, use _method = PUT or DELETE with a POST )
324  *           cfg.onSuccess        -  callback function to capture the success result
325  *           cfg.onLastFailure        -  callback to execute if there is an error
326  *           cfg.content          -  optional content to send with the request, ie {value: 'x', _method: 'PUT'}
327  *
328  *  @returns void, use callbacks
329  *
330  *  Static method.  Allows the user to pass in an array of urls to try.  The first one to return a response stops
331  *  the processing.  Uses the Ozone.util.Transport.send method.
332  */
333 Ozone.util.Transport.sendToFirst = function(cfg) {
334     var u = cfg.urls.shift();
335 	
336     if (u === undefined) {
337         if (cfg.onLastFailure !== undefined) {
338             cfg.onLastFailure();
339         }
340         return;
341     }
342 	
343     var onThisFailure = function() {
344         Ozone.util.Transport.sendToFirst({
345             urls:cfg.urls,
346             method:cfg.method,
347             onSuccess:cfg.onSuccess,
348             onLastFailure:cfg.onLastFailure,
349             content:cfg.content
350             });
351     };
352 	
353     Ozone.util.Transport.send({
354         url:u,
355         method:cfg.method,
356         onSuccess:cfg.onSuccess,
357         onFailure:onThisFailure,
358         content:cfg.content
359         });
360 };
361