cometd-rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/LICENSE +202 -0
- data/README.md +39 -0
- data/Rakefile +2 -0
- data/cometd-rails.gemspec +23 -0
- data/lib/cometd/rails/version.rb +5 -0
- data/lib/cometd/rails.rb +18 -0
- data/vendor/assets/javascripts/.DS_Store +0 -0
- data/vendor/assets/javascripts/cometd-dojox-rails.js +2 -0
- data/vendor/assets/javascripts/cometd-jquery-rails.js +2 -0
- data/vendor/assets/javascripts/common/.DS_Store +0 -0
- data/vendor/assets/javascripts/common/AckExtension.js +112 -0
- data/vendor/assets/javascripts/common/CallbackPollingTransport.js +166 -0
- data/vendor/assets/javascripts/common/CometD.js +2090 -0
- data/vendor/assets/javascripts/common/LongPollingTransport.js +111 -0
- data/vendor/assets/javascripts/common/ReloadExtension.js +254 -0
- data/vendor/assets/javascripts/common/RequestTransport.js +297 -0
- data/vendor/assets/javascripts/common/TimeStampExtension.js +42 -0
- data/vendor/assets/javascripts/common/TimeSyncExtension.js +216 -0
- data/vendor/assets/javascripts/common/Transport.js +142 -0
- data/vendor/assets/javascripts/common/TransportRegistry.js +116 -0
- data/vendor/assets/javascripts/common/Utils.js +58 -0
- data/vendor/assets/javascripts/common/WebSocketTransport.js +410 -0
- data/vendor/assets/javascripts/common/cometd-amd.js +7 -0
- data/vendor/assets/javascripts/common/cometd-header.js +15 -0
- data/vendor/assets/javascripts/common/cometd-json.js +5 -0
- data/vendor/assets/javascripts/common/cometd-namespace.js +3 -0
- data/vendor/assets/javascripts/common/cometd.require.js +16 -0
- data/vendor/assets/javascripts/dojox/.DS_Store +0 -0
- data/vendor/assets/javascripts/dojox/ack.js +22 -0
- data/vendor/assets/javascripts/dojox/dojox.require.js +5 -0
- data/vendor/assets/javascripts/dojox/main.js +95 -0
- data/vendor/assets/javascripts/dojox/reload.js +26 -0
- data/vendor/assets/javascripts/dojox/timestamp.js +22 -0
- data/vendor/assets/javascripts/dojox/timesync.js +22 -0
- data/vendor/assets/javascripts/jquery/.DS_Store +0 -0
- data/vendor/assets/javascripts/jquery/jquery.cometd-ack.js +33 -0
- data/vendor/assets/javascripts/jquery/jquery.cometd-reload.js +41 -0
- data/vendor/assets/javascripts/jquery/jquery.cometd-timestamp.js +33 -0
- data/vendor/assets/javascripts/jquery/jquery.cometd-timesync.js +33 -0
- data/vendor/assets/javascripts/jquery/jquery.cometd.js +140 -0
- data/vendor/assets/javascripts/jquery/jquery.cometd.require.js +5 -0
- metadata +115 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
org.cometd.LongPollingTransport = function()
|
2
|
+
{
|
3
|
+
var _super = new org.cometd.RequestTransport();
|
4
|
+
var _self = org.cometd.Transport.derive(_super);
|
5
|
+
// By default, support cross domain
|
6
|
+
var _supportsCrossDomain = true;
|
7
|
+
|
8
|
+
_self.accept = function(version, crossDomain, url)
|
9
|
+
{
|
10
|
+
return _supportsCrossDomain || !crossDomain;
|
11
|
+
};
|
12
|
+
|
13
|
+
_self.xhrSend = function(packet)
|
14
|
+
{
|
15
|
+
throw 'Abstract';
|
16
|
+
};
|
17
|
+
|
18
|
+
_self.transportSend = function(envelope, request)
|
19
|
+
{
|
20
|
+
this._debug('Transport', this.getType(), 'sending request', request.id, 'envelope', envelope);
|
21
|
+
|
22
|
+
var self = this;
|
23
|
+
try
|
24
|
+
{
|
25
|
+
var sameStack = true;
|
26
|
+
request.xhr = this.xhrSend({
|
27
|
+
transport: this,
|
28
|
+
url: envelope.url,
|
29
|
+
sync: envelope.sync,
|
30
|
+
headers: this.getConfiguration().requestHeaders,
|
31
|
+
body: org.cometd.JSON.toJSON(envelope.messages),
|
32
|
+
onSuccess: function(response)
|
33
|
+
{
|
34
|
+
self._debug('Transport', self.getType(), 'received response', response);
|
35
|
+
var success = false;
|
36
|
+
try
|
37
|
+
{
|
38
|
+
var received = self.convertToMessages(response);
|
39
|
+
if (received.length === 0)
|
40
|
+
{
|
41
|
+
_supportsCrossDomain = false;
|
42
|
+
self.transportFailure(envelope, request, {
|
43
|
+
httpCode: 204
|
44
|
+
});
|
45
|
+
}
|
46
|
+
else
|
47
|
+
{
|
48
|
+
success = true;
|
49
|
+
self.transportSuccess(envelope, request, received);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
catch(x)
|
53
|
+
{
|
54
|
+
self._debug(x);
|
55
|
+
if (!success)
|
56
|
+
{
|
57
|
+
_supportsCrossDomain = false;
|
58
|
+
var failure = {
|
59
|
+
exception: x
|
60
|
+
};
|
61
|
+
failure.httpCode = self.xhrStatus(request.xhr);
|
62
|
+
self.transportFailure(envelope, request, failure);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
},
|
66
|
+
onError: function(reason, exception)
|
67
|
+
{
|
68
|
+
self._debug('Transport', self.getType(), 'received error', reason, exception);
|
69
|
+
_supportsCrossDomain = false;
|
70
|
+
var failure = {
|
71
|
+
reason: reason,
|
72
|
+
exception: exception
|
73
|
+
};
|
74
|
+
failure.httpCode = self.xhrStatus(request.xhr);
|
75
|
+
if (sameStack)
|
76
|
+
{
|
77
|
+
// Keep the semantic of calling response callbacks asynchronously after the request
|
78
|
+
self.setTimeout(function()
|
79
|
+
{
|
80
|
+
self.transportFailure(envelope, request, failure);
|
81
|
+
}, 0);
|
82
|
+
}
|
83
|
+
else
|
84
|
+
{
|
85
|
+
self.transportFailure(envelope, request, failure);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
});
|
89
|
+
sameStack = false;
|
90
|
+
}
|
91
|
+
catch (x)
|
92
|
+
{
|
93
|
+
_supportsCrossDomain = false;
|
94
|
+
// Keep the semantic of calling response callbacks asynchronously after the request
|
95
|
+
this.setTimeout(function()
|
96
|
+
{
|
97
|
+
self.transportFailure(envelope, request, {
|
98
|
+
exception: x
|
99
|
+
});
|
100
|
+
}, 0);
|
101
|
+
}
|
102
|
+
};
|
103
|
+
|
104
|
+
_self.reset = function()
|
105
|
+
{
|
106
|
+
_super.reset();
|
107
|
+
_supportsCrossDomain = true;
|
108
|
+
};
|
109
|
+
|
110
|
+
return _self;
|
111
|
+
};
|
@@ -0,0 +1,254 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2010 the original author or authors.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* 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
|
+
(function()
|
18
|
+
{
|
19
|
+
function bind(org_cometd)
|
20
|
+
{
|
21
|
+
if (!org_cometd.COOKIE)
|
22
|
+
{
|
23
|
+
org_cometd.COOKIE = {};
|
24
|
+
org_cometd.COOKIE.set = function(name, value, options)
|
25
|
+
{
|
26
|
+
throw 'Abstract';
|
27
|
+
};
|
28
|
+
org_cometd.COOKIE.get = function(name)
|
29
|
+
{
|
30
|
+
throw 'Abstract';
|
31
|
+
};
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* The reload extension allows a page to be loaded (or reloaded)
|
36
|
+
* without having to re-handshake in the new (or reloaded) page,
|
37
|
+
* therefore resuming the existing cometd connection.
|
38
|
+
*
|
39
|
+
* When the reload() method is called, the state of the cometd
|
40
|
+
* connection and of the cometd subscriptions is stored in a cookie
|
41
|
+
* with a short max-age.
|
42
|
+
* The reload() method must therefore be called by page unload
|
43
|
+
* handlers, often provided by JavaScript toolkits.
|
44
|
+
*
|
45
|
+
* When the page is (re)loaded, this extension checks the cookie
|
46
|
+
* and restores the cometd connection and the cometd subscriptions.
|
47
|
+
*/
|
48
|
+
return org_cometd.ReloadExtension = function(configuration)
|
49
|
+
{
|
50
|
+
var _cometd;
|
51
|
+
var _debug;
|
52
|
+
var _state = null;
|
53
|
+
var _cookieName = 'org.cometd.reload';
|
54
|
+
var _cookiePath = '/';
|
55
|
+
var _cookieMaxAge = 5;
|
56
|
+
var _batch = false;
|
57
|
+
|
58
|
+
function _reload(config)
|
59
|
+
{
|
60
|
+
if (_state && _state.handshakeResponse !== null)
|
61
|
+
{
|
62
|
+
_configure(config);
|
63
|
+
_state.cookiePath = _cookiePath;
|
64
|
+
var cookie = org_cometd.JSON.toJSON(_state);
|
65
|
+
_debug('Reload extension saving cookie value', cookie);
|
66
|
+
org_cometd.COOKIE.set(_cookieName, cookie, {
|
67
|
+
'max-age': _cookieMaxAge,
|
68
|
+
path: _cookiePath,
|
69
|
+
expires: new Date(new Date().getTime() + _cookieMaxAge * 1000)
|
70
|
+
});
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
function _similarState(oldState)
|
75
|
+
{
|
76
|
+
// We want to check here that the CometD object
|
77
|
+
// did not change much between reloads.
|
78
|
+
// We just check the URL for now, but in future
|
79
|
+
// further checks may involve the transport type
|
80
|
+
// and other configuration parameters.
|
81
|
+
return _state.url == oldState.url;
|
82
|
+
}
|
83
|
+
|
84
|
+
function _configure(config)
|
85
|
+
{
|
86
|
+
if (config)
|
87
|
+
{
|
88
|
+
if (typeof config.cookieMaxAge === 'number')
|
89
|
+
{
|
90
|
+
_cookieMaxAge = config.cookieMaxAge;
|
91
|
+
}
|
92
|
+
if (typeof config.cookieName === 'string')
|
93
|
+
{
|
94
|
+
_cookieName = config.cookieName;
|
95
|
+
}
|
96
|
+
if (typeof config.cookiePath === 'string')
|
97
|
+
{
|
98
|
+
_cookiePath = config.cookiePath;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
this.configure = _configure;
|
104
|
+
|
105
|
+
this.registered = function(name, cometd)
|
106
|
+
{
|
107
|
+
_cometd = cometd;
|
108
|
+
_cometd.reload = _reload;
|
109
|
+
_debug = _cometd._debug;
|
110
|
+
};
|
111
|
+
|
112
|
+
this.unregistered = function()
|
113
|
+
{
|
114
|
+
delete _cometd.reload;
|
115
|
+
_cometd = null;
|
116
|
+
};
|
117
|
+
|
118
|
+
this.outgoing = function(message)
|
119
|
+
{
|
120
|
+
switch (message.channel)
|
121
|
+
{
|
122
|
+
case '/meta/handshake':
|
123
|
+
{
|
124
|
+
_state = {};
|
125
|
+
_state.url = _cometd.getURL();
|
126
|
+
|
127
|
+
var cookie = org_cometd.COOKIE.get(_cookieName);
|
128
|
+
_debug('Reload extension found cookie value', cookie);
|
129
|
+
// Is there a saved handshake response from a prior load ?
|
130
|
+
if (cookie)
|
131
|
+
{
|
132
|
+
try
|
133
|
+
{
|
134
|
+
var oldState = org_cometd.JSON.fromJSON(cookie);
|
135
|
+
|
136
|
+
// Remove the cookie, not needed anymore
|
137
|
+
org_cometd.COOKIE.set(_cookieName, '', {
|
138
|
+
'max-age': -1,
|
139
|
+
path: oldState.cookiePath,
|
140
|
+
expires: -1
|
141
|
+
});
|
142
|
+
|
143
|
+
if (oldState.handshakeResponse && _similarState(oldState))
|
144
|
+
{
|
145
|
+
_debug('Reload extension restoring state', oldState);
|
146
|
+
setTimeout(function ()
|
147
|
+
{
|
148
|
+
_debug('Reload extension replaying handshake response', oldState.handshakeResponse);
|
149
|
+
_state.handshakeResponse = oldState.handshakeResponse;
|
150
|
+
_state.transportType = oldState.transportType;
|
151
|
+
_state.reloading = true;
|
152
|
+
var response = _cometd._mixin(true, {}, _state.handshakeResponse, {ext: {reload: true}});
|
153
|
+
response.supportedConnectionTypes = [_state.transportType];
|
154
|
+
_cometd.receive(response);
|
155
|
+
_debug('Reload extension replayed handshake response', response);
|
156
|
+
}, 0);
|
157
|
+
|
158
|
+
// delay any sends until first connect is complete.
|
159
|
+
if (!_batch)
|
160
|
+
{
|
161
|
+
_batch = true;
|
162
|
+
_cometd.startBatch();
|
163
|
+
}
|
164
|
+
// This handshake is aborted, as we will replay the prior handshake response
|
165
|
+
return null;
|
166
|
+
}
|
167
|
+
else
|
168
|
+
{
|
169
|
+
_debug('Reload extension could not restore state', oldState);
|
170
|
+
}
|
171
|
+
}
|
172
|
+
catch (x)
|
173
|
+
{
|
174
|
+
_debug('Reload extension error while trying to restore cookie', x);
|
175
|
+
}
|
176
|
+
}
|
177
|
+
break;
|
178
|
+
}
|
179
|
+
case '/meta/connect':
|
180
|
+
{
|
181
|
+
if (!_state.transportType)
|
182
|
+
{
|
183
|
+
_state.transportType = message.connectionType;
|
184
|
+
_debug('Reload extension tracked transport type', _state.transportType);
|
185
|
+
}
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
case '/meta/disconnect':
|
189
|
+
{
|
190
|
+
_state = null;
|
191
|
+
break;
|
192
|
+
}
|
193
|
+
default:
|
194
|
+
{
|
195
|
+
break;
|
196
|
+
}
|
197
|
+
}
|
198
|
+
return message;
|
199
|
+
};
|
200
|
+
|
201
|
+
this.incoming = function(message)
|
202
|
+
{
|
203
|
+
if (message.successful)
|
204
|
+
{
|
205
|
+
switch (message.channel)
|
206
|
+
{
|
207
|
+
case '/meta/handshake':
|
208
|
+
{
|
209
|
+
// If the handshake response is already present, then we're replaying it.
|
210
|
+
// Since the replay may have modified the handshake response, do not record it here.
|
211
|
+
if (!_state.handshakeResponse)
|
212
|
+
{
|
213
|
+
// Save successful handshake response
|
214
|
+
_state.handshakeResponse = message;
|
215
|
+
_debug('Reload extension tracked handshake response', message);
|
216
|
+
}
|
217
|
+
break;
|
218
|
+
}
|
219
|
+
case '/meta/disconnect':
|
220
|
+
{
|
221
|
+
_state = null;
|
222
|
+
break;
|
223
|
+
}
|
224
|
+
case '/meta/connect':
|
225
|
+
{
|
226
|
+
if (_batch)
|
227
|
+
{
|
228
|
+
_cometd.endBatch();
|
229
|
+
_batch = false;
|
230
|
+
}
|
231
|
+
break;
|
232
|
+
}
|
233
|
+
default:
|
234
|
+
{
|
235
|
+
break;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
}
|
239
|
+
return message;
|
240
|
+
};
|
241
|
+
|
242
|
+
_configure(configuration);
|
243
|
+
};
|
244
|
+
}
|
245
|
+
|
246
|
+
if (typeof define === 'function' && define.amd)
|
247
|
+
{
|
248
|
+
define(['org/cometd'], bind);
|
249
|
+
}
|
250
|
+
else
|
251
|
+
{
|
252
|
+
bind(org.cometd);
|
253
|
+
}
|
254
|
+
})();
|
@@ -0,0 +1,297 @@
|
|
1
|
+
/**
|
2
|
+
* Base object with the common functionality for transports based on requests.
|
3
|
+
* The key responsibility is to allow at most 2 outstanding requests to the server,
|
4
|
+
* to avoid that requests are sent behind a long poll.
|
5
|
+
* To achieve this, we have one reserved request for the long poll, and all other
|
6
|
+
* requests are serialized one after the other.
|
7
|
+
*/
|
8
|
+
org.cometd.RequestTransport = function()
|
9
|
+
{
|
10
|
+
var _super = new org.cometd.Transport();
|
11
|
+
var _self = org.cometd.Transport.derive(_super);
|
12
|
+
var _requestIds = 0;
|
13
|
+
var _metaConnectRequest = null;
|
14
|
+
var _requests = [];
|
15
|
+
var _envelopes = [];
|
16
|
+
|
17
|
+
function _coalesceEnvelopes(envelope)
|
18
|
+
{
|
19
|
+
while (_envelopes.length > 0)
|
20
|
+
{
|
21
|
+
var envelopeAndRequest = _envelopes[0];
|
22
|
+
var newEnvelope = envelopeAndRequest[0];
|
23
|
+
var newRequest = envelopeAndRequest[1];
|
24
|
+
if (newEnvelope.url === envelope.url &&
|
25
|
+
newEnvelope.sync === envelope.sync)
|
26
|
+
{
|
27
|
+
_envelopes.shift();
|
28
|
+
envelope.messages = envelope.messages.concat(newEnvelope.messages);
|
29
|
+
this._debug('Coalesced', newEnvelope.messages.length, 'messages from request', newRequest.id);
|
30
|
+
continue;
|
31
|
+
}
|
32
|
+
break;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
function _transportSend(envelope, request)
|
37
|
+
{
|
38
|
+
this.transportSend(envelope, request);
|
39
|
+
request.expired = false;
|
40
|
+
|
41
|
+
if (!envelope.sync)
|
42
|
+
{
|
43
|
+
var maxDelay = this.getConfiguration().maxNetworkDelay;
|
44
|
+
var delay = maxDelay;
|
45
|
+
if (request.metaConnect === true)
|
46
|
+
{
|
47
|
+
delay += this.getAdvice().timeout;
|
48
|
+
}
|
49
|
+
|
50
|
+
this._debug('Transport', this.getType(), 'waiting at most', delay, 'ms for the response, maxNetworkDelay', maxDelay);
|
51
|
+
|
52
|
+
var self = this;
|
53
|
+
request.timeout = this.setTimeout(function()
|
54
|
+
{
|
55
|
+
request.expired = true;
|
56
|
+
var errorMessage = 'Request ' + request.id + ' of transport ' + self.getType() + ' exceeded ' + delay + ' ms max network delay';
|
57
|
+
var failure = {
|
58
|
+
reason: errorMessage
|
59
|
+
};
|
60
|
+
var xhr = request.xhr;
|
61
|
+
failure.httpCode = self.xhrStatus(xhr);
|
62
|
+
self.abortXHR(xhr);
|
63
|
+
self._debug(errorMessage);
|
64
|
+
self.complete(request, false, request.metaConnect);
|
65
|
+
envelope.onFailure(xhr, envelope.messages, failure);
|
66
|
+
}, delay);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
function _queueSend(envelope)
|
71
|
+
{
|
72
|
+
var requestId = ++_requestIds;
|
73
|
+
var request = {
|
74
|
+
id: requestId,
|
75
|
+
metaConnect: false,
|
76
|
+
envelope: envelope
|
77
|
+
};
|
78
|
+
|
79
|
+
// Consider the metaConnect requests which should always be present
|
80
|
+
if (_requests.length < this.getConfiguration().maxConnections - 1)
|
81
|
+
{
|
82
|
+
_requests.push(request);
|
83
|
+
_transportSend.call(this, envelope, request);
|
84
|
+
}
|
85
|
+
else
|
86
|
+
{
|
87
|
+
this._debug('Transport', this.getType(), 'queueing request', requestId, 'envelope', envelope);
|
88
|
+
_envelopes.push([envelope, request]);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
function _metaConnectComplete(request)
|
93
|
+
{
|
94
|
+
var requestId = request.id;
|
95
|
+
this._debug('Transport', this.getType(), 'metaConnect complete, request', requestId);
|
96
|
+
if (_metaConnectRequest !== null && _metaConnectRequest.id !== requestId)
|
97
|
+
{
|
98
|
+
throw 'Longpoll request mismatch, completing request ' + requestId;
|
99
|
+
}
|
100
|
+
|
101
|
+
// Reset metaConnect request
|
102
|
+
_metaConnectRequest = null;
|
103
|
+
}
|
104
|
+
|
105
|
+
function _complete(request, success)
|
106
|
+
{
|
107
|
+
var index = org.cometd.Utils.inArray(request, _requests);
|
108
|
+
// The index can be negative if the request has been aborted
|
109
|
+
if (index >= 0)
|
110
|
+
{
|
111
|
+
_requests.splice(index, 1);
|
112
|
+
}
|
113
|
+
|
114
|
+
if (_envelopes.length > 0)
|
115
|
+
{
|
116
|
+
var envelopeAndRequest = _envelopes.shift();
|
117
|
+
var nextEnvelope = envelopeAndRequest[0];
|
118
|
+
var nextRequest = envelopeAndRequest[1];
|
119
|
+
this._debug('Transport dequeued request', nextRequest.id);
|
120
|
+
if (success)
|
121
|
+
{
|
122
|
+
if (this.getConfiguration().autoBatch)
|
123
|
+
{
|
124
|
+
_coalesceEnvelopes.call(this, nextEnvelope);
|
125
|
+
}
|
126
|
+
_queueSend.call(this, nextEnvelope);
|
127
|
+
this._debug('Transport completed request', request.id, nextEnvelope);
|
128
|
+
}
|
129
|
+
else
|
130
|
+
{
|
131
|
+
// Keep the semantic of calling response callbacks asynchronously after the request
|
132
|
+
var self = this;
|
133
|
+
this.setTimeout(function()
|
134
|
+
{
|
135
|
+
self.complete(nextRequest, false, nextRequest.metaConnect);
|
136
|
+
var failure = {
|
137
|
+
reason: 'Previous request failed'
|
138
|
+
};
|
139
|
+
var xhr = nextRequest.xhr;
|
140
|
+
failure.httpCode = self.xhrStatus(xhr);
|
141
|
+
nextEnvelope.onFailure(xhr, nextEnvelope.messages, failure);
|
142
|
+
}, 0);
|
143
|
+
}
|
144
|
+
}
|
145
|
+
}
|
146
|
+
|
147
|
+
_self.complete = function(request, success, metaConnect)
|
148
|
+
{
|
149
|
+
if (metaConnect)
|
150
|
+
{
|
151
|
+
_metaConnectComplete.call(this, request);
|
152
|
+
}
|
153
|
+
else
|
154
|
+
{
|
155
|
+
_complete.call(this, request, success);
|
156
|
+
}
|
157
|
+
};
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Performs the actual send depending on the transport type details.
|
161
|
+
* @param envelope the envelope to send
|
162
|
+
* @param request the request information
|
163
|
+
*/
|
164
|
+
_self.transportSend = function(envelope, request)
|
165
|
+
{
|
166
|
+
throw 'Abstract';
|
167
|
+
};
|
168
|
+
|
169
|
+
_self.transportSuccess = function(envelope, request, responses)
|
170
|
+
{
|
171
|
+
if (!request.expired)
|
172
|
+
{
|
173
|
+
this.clearTimeout(request.timeout);
|
174
|
+
this.complete(request, true, request.metaConnect);
|
175
|
+
if (responses && responses.length > 0)
|
176
|
+
{
|
177
|
+
envelope.onSuccess(responses);
|
178
|
+
}
|
179
|
+
else
|
180
|
+
{
|
181
|
+
envelope.onFailure(request.xhr, envelope.messages, {
|
182
|
+
httpCode: 204
|
183
|
+
});
|
184
|
+
}
|
185
|
+
}
|
186
|
+
};
|
187
|
+
|
188
|
+
_self.transportFailure = function(envelope, request, failure)
|
189
|
+
{
|
190
|
+
if (!request.expired)
|
191
|
+
{
|
192
|
+
this.clearTimeout(request.timeout);
|
193
|
+
this.complete(request, false, request.metaConnect);
|
194
|
+
envelope.onFailure(request.xhr, envelope.messages, failure);
|
195
|
+
}
|
196
|
+
};
|
197
|
+
|
198
|
+
function _metaConnectSend(envelope)
|
199
|
+
{
|
200
|
+
if (_metaConnectRequest !== null)
|
201
|
+
{
|
202
|
+
throw 'Concurrent metaConnect requests not allowed, request id=' + _metaConnectRequest.id + ' not yet completed';
|
203
|
+
}
|
204
|
+
|
205
|
+
var requestId = ++_requestIds;
|
206
|
+
this._debug('Transport', this.getType(), 'metaConnect send, request', requestId, 'envelope', envelope);
|
207
|
+
var request = {
|
208
|
+
id: requestId,
|
209
|
+
metaConnect: true,
|
210
|
+
envelope: envelope
|
211
|
+
};
|
212
|
+
_transportSend.call(this, envelope, request);
|
213
|
+
_metaConnectRequest = request;
|
214
|
+
}
|
215
|
+
|
216
|
+
_self.send = function(envelope, metaConnect)
|
217
|
+
{
|
218
|
+
if (metaConnect)
|
219
|
+
{
|
220
|
+
_metaConnectSend.call(this, envelope);
|
221
|
+
}
|
222
|
+
else
|
223
|
+
{
|
224
|
+
_queueSend.call(this, envelope);
|
225
|
+
}
|
226
|
+
};
|
227
|
+
|
228
|
+
_self.abort = function()
|
229
|
+
{
|
230
|
+
_super.abort();
|
231
|
+
for (var i = 0; i < _requests.length; ++i)
|
232
|
+
{
|
233
|
+
var request = _requests[i];
|
234
|
+
if (request)
|
235
|
+
{
|
236
|
+
this._debug('Aborting request', request);
|
237
|
+
if (!this.abortXHR(request.xhr))
|
238
|
+
{
|
239
|
+
this.transportFailure(request.envelope, request, {reason: 'abort'});
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
if (_metaConnectRequest)
|
244
|
+
{
|
245
|
+
this._debug('Aborting metaConnect request', _metaConnectRequest);
|
246
|
+
if (!this.abortXHR(_metaConnectRequest.xhr))
|
247
|
+
{
|
248
|
+
this.transportFailure(_metaConnectRequest.envelope, _metaConnectRequest, {reason: 'abort'});
|
249
|
+
}
|
250
|
+
}
|
251
|
+
this.reset();
|
252
|
+
};
|
253
|
+
|
254
|
+
_self.reset = function()
|
255
|
+
{
|
256
|
+
_super.reset();
|
257
|
+
_metaConnectRequest = null;
|
258
|
+
_requests = [];
|
259
|
+
_envelopes = [];
|
260
|
+
};
|
261
|
+
|
262
|
+
_self.abortXHR = function(xhr)
|
263
|
+
{
|
264
|
+
if (xhr)
|
265
|
+
{
|
266
|
+
try
|
267
|
+
{
|
268
|
+
var state = xhr.readyState;
|
269
|
+
xhr.abort();
|
270
|
+
return state !== XMLHttpRequest.UNSENT;
|
271
|
+
}
|
272
|
+
catch (x)
|
273
|
+
{
|
274
|
+
this._debug(x);
|
275
|
+
}
|
276
|
+
}
|
277
|
+
return false;
|
278
|
+
};
|
279
|
+
|
280
|
+
_self.xhrStatus = function(xhr)
|
281
|
+
{
|
282
|
+
if (xhr)
|
283
|
+
{
|
284
|
+
try
|
285
|
+
{
|
286
|
+
return xhr.status;
|
287
|
+
}
|
288
|
+
catch (x)
|
289
|
+
{
|
290
|
+
this._debug(x);
|
291
|
+
}
|
292
|
+
}
|
293
|
+
return -1;
|
294
|
+
};
|
295
|
+
|
296
|
+
return _self;
|
297
|
+
};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2010 the original author or authors.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* 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
|
+
(function()
|
18
|
+
{
|
19
|
+
function bind(org_cometd)
|
20
|
+
{
|
21
|
+
/**
|
22
|
+
* The timestamp extension adds the optional timestamp field to all outgoing messages.
|
23
|
+
*/
|
24
|
+
return org_cometd.TimeStampExtension = function()
|
25
|
+
{
|
26
|
+
this.outgoing = function(message)
|
27
|
+
{
|
28
|
+
message.timestamp = new Date().toUTCString();
|
29
|
+
return message;
|
30
|
+
};
|
31
|
+
};
|
32
|
+
}
|
33
|
+
|
34
|
+
if (typeof define === 'function' && define.amd)
|
35
|
+
{
|
36
|
+
define(['org/cometd'], bind);
|
37
|
+
}
|
38
|
+
else
|
39
|
+
{
|
40
|
+
bind(org.cometd);
|
41
|
+
}
|
42
|
+
}());
|