      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