1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to you under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @class 19 * @name _Transports 20 * @memberOf myfaces._impl.xhrCore 21 * @description 22 * 23 * The xhr core adapter 24 * which provides the transport mechanisms to the calling 25 * objects, and controls the queue behavior, the error handling 26 * and partial page submit functionality among other things 27 * <p /> 28 * The idea behind this is to make the ajax request object as barebones 29 * as possible and shift the extra functionality like queuing 30 * parameter handling etc... to this class so that our transports become more easily 31 * pluggable. This should keep the path open to iframe submits and other transport layers 32 * <p /> 33 * the call to the corresponding transport just should be a 34 * transport.xhrQueuedPost <br /> 35 * or transport.xhrPost,transport.xhrGet etc... in the future 36 * <p /> 37 * Note we have taken a pattern lesson or two from the dojo toolkit and its excellent handling 38 * of transports by our patterns here (which is mainly a centralized transport singleton which routes 39 * to different transport implementations and the auto passing of parameters into their 40 * corresponding protected attributes on class level in the transports themselves) 41 */ 42 myfaces._impl.core._Runtime.extendClass("myfaces._impl.xhrCore._Transports" , Object, 43 /** @lends myfaces._impl.xhrCore._Transports.prototype */ { 44 45 _PAR_ERRORLEVEL:"errorlevel", 46 _PAR_QUEUESIZE:"queuesize", 47 _PAR_PPS:"pps", 48 _PAR_TIMEOUT:"timeout", 49 _PAR_DELAY:"delay", 50 51 52 /** 53 * a singleton queue 54 * note the structure of our inheritance 55 * is that that _queue is attached to prototype 56 * and hence the pointer to the request qeue 57 * is shared over all instances 58 * 59 * if you need to have it per instance for complex objects 60 * you have to initialize in the constructor 61 * 62 * (This is the same limitation dojo class inheritance 63 * where our inheritance pattern is derived from has) 64 */ 65 _q: new myfaces._impl.xhrCore._AjaxRequestQueue(), 66 67 68 69 _Lang : myfaces._impl._util._Lang, 70 _RT: myfaces._impl.core._Runtime, 71 72 73 /** 74 * a simple not enqueued xhr post 75 * 76 * mapped options already have the exec and view properly in place 77 * myfaces specifics can be found under mappedOptions.myFaces 78 * @param {Node} source the source of this call 79 * @param {Node} sourceForm the html form which is the source of this call 80 * @param {Object} context (Map) the internal pass through context 81 * @param {Object} passThrgh (Map) values to be passed through 82 **/ 83 xhrPost : function(source, sourceForm, context, passThrgh) { 84 var args = this._getArguments(source, sourceForm, context, passThrgh); 85 delete args.xhrQueue; 86 (new (this._getAjaxReqClass(context))(args)).send(); 87 }, 88 89 /** 90 * xhr post with enqueuing as defined by the jsf 2.0 specification 91 * 92 * mapped options already have the exec and view properly in place 93 * myfaces specifics can be found under mappedOptions.myFaces 94 * @param {Node} source the source of this call 95 * @param {Node} sourceForm the html form which is the source of this call 96 * @param {Object} context (Map) the internal pass through context 97 * @param {Object} passThrgh (Map) values to be passed through 98 **/ 99 xhrQueuedPost : function(source, sourceForm, context, passThrgh) { 100 this._q.enqueue( 101 new (this._getAjaxReqClass(context))(this._getArguments(source, sourceForm, context, passThrgh))); 102 }, 103 104 /** 105 * xhr get without enqueuing 106 * 107 * mapped options already have the exec and view properly in place 108 * myfaces specifics can be found under mappedOptions.myFaces 109 * @param {Node} source the source of this call 110 * @param {Node} sourceForm the html form which is the source of this call 111 * @param {Object} context (Map) the internal pass through context 112 * @param {Object} passThrgh (Map) values to be passed through 113 **/ 114 xhrGet : function(source, sourceForm, context, passThrgh) { 115 var args = this._getArguments(source, sourceForm, context, passThrgh); 116 // note in get the timeout is not working delay however is and queue size as well 117 // since there are no cross browser ways to resolve a timeout on xhr level 118 // we have to live with it 119 args.ajaxType = "GET"; 120 delete args.xhrQueue; 121 (new (this._getAjaxReqClass(context))(args)).send(); 122 }, 123 124 /** 125 * xhr get which takes the existing queue into consideration to by synchronized 126 * to previous queued post requests 127 * 128 * mapped options already have the exec and view properly in place 129 * myfaces specifics can be found under mappedOptions.myFaces 130 * @param {Node} source the source of this call 131 * @param {Node} sourceForm the html form which is the source of this call 132 * @param {Object} context (Map) the internal pass through context 133 * @param {Object} passThrgh (Map) values to be passed through 134 **/ 135 xhrQueuedGet : function(source, sourceForm, context, passThrgh) { 136 var args = this._getArguments(source, sourceForm, context, passThrgh); 137 // note in get the timeout is not working delay however is and queue size as well 138 // since there are no cross browser ways to resolve a timeout on xhr level 139 // we have to live with it 140 args.ajaxType = "GET"; 141 this._q.enqueue( 142 new (this._getAjaxReqClass(context))(args)); 143 }, 144 145 146 /** 147 * iframe post without queueing 148 * 149 * mapped options already have the exec and view properly in place 150 * myfaces specifics can be found under mappedOptions.myFaces 151 * @param {Node} source the source of this call 152 * @param {Node} sourceForm the html form which is the source of this call 153 * @param {Object} context (Map) the internal pass through context 154 * @param {Object} passThrgh (Map) values to be passed through 155 **/ 156 multipartPost : function(source, sourceForm, context, passThrgh) { 157 var args = this._getArguments(source, sourceForm, context, passThrgh); 158 // note in get the timeout is not working delay however is and queue size as well 159 // since there are no cross browser ways to resolve a timeout on xhr level 160 // we have to live with it 161 delete args.xhrQueue; 162 (new (this._getMultipartReqClass(context))(args)).send(); 163 }, 164 165 /** 166 * iframe queued post 167 * 168 * mapped options already have the exec and view properly in place 169 * myfaces specifics can be found under mappedOptions.myFaces 170 * @param {Node} source the source of this call 171 * @param {Node} sourceForm the html form which is the source of this call 172 * @param {Object} context (Map) the internal pass through context 173 * @param {Object} passThrgh (Map) values to be passed through 174 **/ 175 multipartQueuedPost : function(source, sourceForm, context, passThrgh) { 176 var args = this._getArguments(source, sourceForm, context, passThrgh); 177 // note in get the timeout is not working delay however is and queue size as well 178 // since there are no cross browser ways to resolve a timeout on xhr level 179 this._q.enqueue( 180 new (this._getMultipartReqClass(context))(args)); 181 }, 182 183 184 /** 185 * iframe get without queueing 186 * 187 * mapped options already have the exec and view properly in place 188 * myfaces specifics can be found under mappedOptions.myFaces 189 * @param {Node} source the source of this call 190 * @param {Node} sourceForm the html form which is the source of this call 191 * @param {Object} context (Map) the internal pass through context 192 * @param {Object} passThrgh (Map) values to be passed through 193 **/ 194 multipartGet : function(source, sourceForm, context, passThrgh) { 195 var args = this._getArguments(source, sourceForm, context, passThrgh); 196 // note in get the timeout is not working delay however is and queue size as well 197 // since there are no cross browser ways to resolve a timeout on xhr level 198 // we have to live with it 199 args.ajaxType = "GET"; 200 delete args.xhrQueue; 201 (new (this._getMultipartReqClass(context))(args)).send(); 202 }, 203 204 /** 205 * iframe queued http get 206 * 207 * mapped options already have the exec and view properly in place 208 * myfaces specifics can be found under mappedOptions.myFaces 209 * @param {Node} source the source of this call 210 * @param {Node} sourceForm the html form which is the source of this call 211 * @param {Object} context (Map) the internal pass through context 212 * @param {Object} passThrgh (Map) values to be passed through 213 **/ 214 multipartQueuedGet : function(source, sourceForm, context, passThrgh) { 215 var args = this._getArguments(source, sourceForm, context, passThrgh); 216 // note in get the timeout is not working delay however is and queue size as well 217 // since there are no cross browser ways to resolve a timeout on xhr level 218 args.ajaxType = "GET"; 219 this._q.enqueue( 220 new (this._getMultipartReqClass(context))(args)); 221 }, 222 223 224 /** 225 * Spec. 13.3.3 226 * Examining the response markup and updating the DOM tree 227 * @param {XmlHttpRequest} request - the ajax request 228 * @param {XmlHttpRequest} context - the ajax context 229 */ 230 response : function(request, context) { 231 var internalContext = context._mfInternal; 232 233 //the normal usecase is that the request knows about its response 234 //which normally is temporary stored within the _mfRequest object 235 //(aka call from a finished request) 236 //if no _mfRequest object is given which means an external call we 237 //have a call from the outside 238 239 //TODO check if we cannot eliminate the _mfRequest object in the long run 240 //given we have to pass a request object anyway 241 242 var ajaxObj = (internalContext && internalContext._mfRequest) || new (this._getAjaxReqClass(context))({xhr: request, context: context}); 243 //ie gc fix 244 if(internalContext && internalContext._mfRequest){ 245 internalContext._mfRequest = null; 246 delete internalContext._mfRequest; 247 } 248 249 ajaxObj._response.processResponse(request, context); 250 }, 251 252 /** 253 * creates the arguments map and 254 * fetches the config params in a proper way in to 255 * deal with them in a flat way (from the nested context way) 256 * 257 * @param source the source of the request 258 * @param sourceForm the sourceform 259 * @param context the context holding all values 260 * @param passThrgh the passThrough values to be blended into the response 261 */ 262 _getArguments: function(source, sourceForm, context, passThrgh) { 263 var _RT = myfaces._impl.core._Runtime; 264 /** @ignore */ 265 var _getConfig = _RT.getLocalOrGlobalConfig; 266 var _Lang = myfaces._impl._util._Lang; 267 268 var ret = { 269 "source": source, 270 "sourceForm": sourceForm, 271 "context": context, 272 "passThrough": passThrgh, 273 "xhrQueue": this._q 274 }; 275 276 //we now mix in the config settings which might either be set globally 277 //or pushed in under the context myfaces.<contextValue> into the current request 278 this._applyConfig(ret, context, "alarmThreshold", this._PAR_ERRORLEVEL); 279 this._applyConfig(ret, context, "queueSize", this._PAR_QUEUESIZE); 280 this._applyConfig(ret, context, "timeout", this._PAR_TIMEOUT); 281 this._applyConfig(ret, context, "delay", this._PAR_DELAY); 282 283 //now partial page submit needs a different treatment 284 //since pps == execute strings 285 if (_getConfig(context, this._PAR_PPS, false) 286 && _Lang.exists(passThrgh, myfaces._impl.core.Impl.P_EXECUTE) 287 && passThrgh[myfaces._impl.core.Impl.P_EXECUTE].length > 0) { 288 ret['partialIdsArray'] = passThrgh[myfaces._impl.core.Impl.P_EXECUTE].split(" "); 289 } 290 return ret; 291 }, 292 293 /** 294 * helper method to apply a config setting to our varargs param list 295 * 296 * @param destination the destination map to receive the setting 297 * @param context the current context 298 * @param destParm the destination param of the destination map 299 * @param srcParm the source param which is the key to our config setting 300 */ 301 _applyConfig: function(destination, context, destParm, srcParm) { 302 var _RT = myfaces._impl.core._Runtime; 303 /** @ignore */ 304 var _getConfig = _RT.getLocalOrGlobalConfig; 305 if (_getConfig(context, srcParm, null) != null) { 306 destination[destParm] = _getConfig(context, srcParm, null); 307 } 308 }, 309 310 311 312 313 314 315 316 _loadImpl: function() { 317 if (!this._Impl) { 318 this._Impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl); 319 } 320 return this._Impl; 321 }, 322 323 /** 324 * centralized transport switching helper 325 * for the multipart submit case 326 * 327 * @param context the context which is passed down 328 */ 329 _getMultipartReqClass: function(context) { 330 //if (this._RT.getLocalOrGlobalConfig(context, "transportAutoSelection", false) && this._RT.getXHRLvl() >= 2) { 331 // return myfaces._impl.xhrCore._AjaxRequestLevel2; 332 //} else { 333 return myfaces._impl.xhrCore._IFrameRequest; 334 //} 335 }, 336 337 338 _getAjaxReqClass: function(context) { 339 return myfaces._impl.xhrCore._AjaxRequest; 340 } 341 342 }); 343