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 _MF_SINGLTN(_PFX_XHR + "_Transports", _MF_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          * xhr post with enqueuing as defined by the faces 2.0 specification
 69          *
 70          * mapped options already have the exec and view properly in place
 71          * myfaces specifics can be found under mappedOptions.myFaces
 72          * @param {Node} source the source of this call
 73          * @param {Node} sourceForm the html form which is the source of this call
 74          * @param {Object} context (Map) the internal pass through context
 75          * @param {Object} passThrgh (Map) values to be passed through
 76          **/
 77         xhrQueuedPost: function (source, sourceForm, context, passThrgh) {
 78             this._q.enqueue(
 79                 new (this._getAjaxReqClass(context))(this._getArguments(source, sourceForm, context, passThrgh)));
 80         },
 81 
 82 
 83         /**
 84          * a simple not enqueued xhr post
 85          *
 86          * mapped options already have the exec and view properly in place
 87          * myfaces specifics can be found under mappedOptions.myFaces
 88          * @param {Node} source the source of this call
 89          * @param {Node} sourceForm the html form which is the source of this call
 90          * @param {Object} context (Map) the internal pass through context
 91          * @param {Object} passThrgh (Map) values to be passed through
 92          **/
 93         xhrPost: function (source, sourceForm, context, passThrgh) {
 94             var args = this._getArguments(source, sourceForm, context, passThrgh);
 95             delete args.xhrQueue;
 96             (new (this._getAjaxReqClass(context))(args)).send();
 97         },
 98 
 99 
100         /**
101          * xhr get without enqueuing
102          *
103          * mapped options already have the exec and view properly in place
104          * myfaces specifics can be found under mappedOptions.myFaces
105          * @param {Node} source the source of this call
106          * @param {Node} sourceForm the html form which is the source of this call
107          * @param {Object} context (Map) the internal pass through context
108          * @param {Object} passThrgh (Map) values to be passed through
109          **/
110         xhrGet: function (source, sourceForm, context, passThrgh) {
111             var args = this._getArguments(source, sourceForm, context, passThrgh);
112             // note in get the timeout is not working delay however is and queue size as well
113             // since there are no cross browser ways to resolve a timeout on xhr level
114             // we have to live with it
115             args.ajaxType = "GET";
116             delete args.xhrQueue;
117             (new (this._getAjaxReqClass(context))(args)).send();
118         },
119 
120         /**
121          * xhr get which takes the existing queue into consideration to by synchronized
122          * to previous queued post requests
123          *
124          * mapped options already have the exec and view properly in place
125          * myfaces specifics can be found under mappedOptions.myFaces
126          * @param {Node} source the source of this call
127          * @param {Node} sourceForm the html form which is the source of this call
128          * @param {Object} context (Map) the internal pass through context
129          * @param {Object} passThrgh (Map) values to be passed through
130          **/
131         xhrQueuedGet: function (source, sourceForm, context, passThrgh) {
132             var args = this._getArguments(source, sourceForm, context, passThrgh);
133             // note in get the timeout is not working delay however is and queue size as well
134             // since there are no cross browser ways to resolve a timeout on xhr level
135             // we have to live with it
136             args.ajaxType = "GET";
137             this._q.enqueue(
138                 new (this._getAjaxReqClass(context))(args));
139         },
140 
141 
142         /**
143          * multipart post without queueing
144          *
145          * mapped options already have the exec and view properly in place
146          * myfaces specifics can be found under mappedOptions.myFaces
147          * @param {Node} source the source of this call
148          * @param {Node} sourceForm the html form which is the source of this call
149          * @param {Object} context (Map) the internal pass through context
150          * @param {Object} passThrgh (Map) values to be passed through
151          **/
152         multipartPost: function (source, sourceForm, context, passThrgh) {
153             var args = this._getArguments(source, sourceForm, context, passThrgh);
154             // note in get the timeout is not working delay however is and queue size as well
155             // since there are no cross browser ways to resolve a timeout on xhr level
156             // we have to live with it
157             delete args.xhrQueue;
158             (new (this._getMultipartReqClass(context))(args)).send();
159         },
160 
161         /**
162          * multipart queued post
163          *
164          * mapped options already have the exec and view properly in place
165          * myfaces specifics can be found under mappedOptions.myFaces
166          * @param {Node} source the source of this call
167          * @param {Node} sourceForm the html form which is the source of this call
168          * @param {Object} context (Map) the internal pass through context
169          * @param {Object} passThrgh (Map) values to be passed through
170          **/
171         multipartQueuedPost: function (source, sourceForm, context, passThrgh) {
172             var args = this._getArguments(source, sourceForm, context, passThrgh);
173             // note in get the timeout is not working delay however is and queue size as well
174             // since there are no cross browser ways to resolve a timeout on xhr level
175             this._q.enqueue(
176                 new (this._getMultipartReqClass(context))(args));
177         },
178 
179         /**
180          * iframe get without queueing
181          *
182          * mapped options already have the exec and view properly in place
183          * myfaces specifics can be found under mappedOptions.myFaces
184          * @param {Node} source the source of this call
185          * @param {Node} sourceForm the html form which is the source of this call
186          * @param {Object} context (Map) the internal pass through context
187          * @param {Object} passThrgh (Map) values to be passed through
188          **/
189         multipartGet: function (source, sourceForm, context, passThrgh) {
190             var args = this._getArguments(source, sourceForm, context, passThrgh);
191             // note in get the timeout is not working delay however is and queue size as well
192             // since there are no cross browser ways to resolve a timeout on xhr level
193             // we have to live with it
194             args.ajaxType = "GET";
195             delete args.xhrQueue;
196             (new (this._getMultipartReqClass(context))(args)).send();
197         },
198 
199         /**
200          * multipart queued http get
201          *
202          * mapped options already have the exec and view properly in place
203          * myfaces specifics can be found under mappedOptions.myFaces
204          * @param {Node} source the source of this call
205          * @param {Node} sourceForm the html form which is the source of this call
206          * @param {Object} context (Map) the internal pass through context
207          * @param {Object} passThrgh (Map) values to be passed through
208          **/
209         multipartQueuedGet: function (source, sourceForm, context, passThrgh) {
210             var args = this._getArguments(source, sourceForm, context, passThrgh);
211             // note in get the timeout is not working delay however is and queue size as well
212             // since there are no cross browser ways to resolve a timeout on xhr level
213             args.ajaxType = "GET";
214             this._q.enqueue(
215                 new (this._getMultipartReqClass(context))(args));
216         },
217 
218 
219         /**
220          * creates the arguments map and
221          * fetches the config params in a proper way in to
222          * deal with them in a flat way (from the nested context way)
223          *
224          * @param source the source of the request
225          * @param sourceForm the sourceform
226          * @param context   the context holding all values
227          * @param passThrgh the passThrough values to be blended into the response
228          */
229         _getArguments: function (source, sourceForm, context, passThrgh) {
230             var _RT = myfaces._impl.core._Runtime,
231                 /** @ignore */
232                 _Lang = myfaces._impl._util._Lang,
233                 applyCfg = _Lang.hitch(this, this._applyConfig),
234                 //RT does not have this references, hence no hitch needed
235                 getCfg = _RT.getLocalOrGlobalConfig,
236 
237 
238                 ret = {
239                     "source": source,
240                     "sourceForm": sourceForm,
241                     "context": context,
242                     "passThrough": passThrgh,
243                     "xhrQueue": this._q
244                 };
245 
246             //we now mix in the config settings which might either be set globally
247             //or pushed in under the context myfaces.<contextValue> into the current request
248             applyCfg(ret, context, "alarmThreshold", this._PAR_ERRORLEVEL);
249             applyCfg(ret, context, "queueSize", this._PAR_QUEUESIZE);
250             //TODO timeout probably not needed anymore
251             applyCfg(ret, context, "timeout", this._PAR_TIMEOUT);
252             //applyCfg(ret, context, "delay", this._PAR_DELAY);
253 
254             //now partial page submit needs a different treatment
255             //since pps == execute strings
256             if (getCfg(context, this._PAR_PPS, false)
257                 && _Lang.exists(passThrgh, myfaces._impl.core.Impl.P_EXECUTE)
258                 && passThrgh[myfaces._impl.core.Impl.P_EXECUTE].length > 0) {
259                 ret['partialIdsArray'] = passThrgh[myfaces._impl.core.Impl.P_EXECUTE].split(" ");
260             }
261             return ret;
262         },
263 
264         /**
265          * helper method to apply a config setting to our varargs param list
266          *
267          * @param destination the destination map to receive the setting
268          * @param context the current context
269          * @param destParm the destination param of the destination map
270          * @param srcParm the source param which is the key to our config setting
271          */
272         _applyConfig: function (destination, context, destParm, srcParm) {
273             var _RT = myfaces._impl.core._Runtime;
274             /** @ignore */
275             var _getConfig = _RT.getLocalOrGlobalConfig;
276             if (_getConfig(context, srcParm, null) != null) {
277                 destination[destParm] = _getConfig(context, srcParm, null);
278             }
279         },
280 
281         /**
282          * centralized transport switching helper
283          * for the multipart submit case
284          *
285          * @param context the context which is passed down
286          */
287         _getMultipartReqClass: function (context) {
288             return myfaces._impl.xhrCore._FormDataRequest;
289         },
290 
291 
292         _getAjaxReqClass: function (context) {
293             return myfaces._impl.xhrCore._AjaxRequest;
294         }
295 
296     });
297