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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +202 -0
  5. data/README.md +39 -0
  6. data/Rakefile +2 -0
  7. data/cometd-rails.gemspec +23 -0
  8. data/lib/cometd/rails/version.rb +5 -0
  9. data/lib/cometd/rails.rb +18 -0
  10. data/vendor/assets/javascripts/.DS_Store +0 -0
  11. data/vendor/assets/javascripts/cometd-dojox-rails.js +2 -0
  12. data/vendor/assets/javascripts/cometd-jquery-rails.js +2 -0
  13. data/vendor/assets/javascripts/common/.DS_Store +0 -0
  14. data/vendor/assets/javascripts/common/AckExtension.js +112 -0
  15. data/vendor/assets/javascripts/common/CallbackPollingTransport.js +166 -0
  16. data/vendor/assets/javascripts/common/CometD.js +2090 -0
  17. data/vendor/assets/javascripts/common/LongPollingTransport.js +111 -0
  18. data/vendor/assets/javascripts/common/ReloadExtension.js +254 -0
  19. data/vendor/assets/javascripts/common/RequestTransport.js +297 -0
  20. data/vendor/assets/javascripts/common/TimeStampExtension.js +42 -0
  21. data/vendor/assets/javascripts/common/TimeSyncExtension.js +216 -0
  22. data/vendor/assets/javascripts/common/Transport.js +142 -0
  23. data/vendor/assets/javascripts/common/TransportRegistry.js +116 -0
  24. data/vendor/assets/javascripts/common/Utils.js +58 -0
  25. data/vendor/assets/javascripts/common/WebSocketTransport.js +410 -0
  26. data/vendor/assets/javascripts/common/cometd-amd.js +7 -0
  27. data/vendor/assets/javascripts/common/cometd-header.js +15 -0
  28. data/vendor/assets/javascripts/common/cometd-json.js +5 -0
  29. data/vendor/assets/javascripts/common/cometd-namespace.js +3 -0
  30. data/vendor/assets/javascripts/common/cometd.require.js +16 -0
  31. data/vendor/assets/javascripts/dojox/.DS_Store +0 -0
  32. data/vendor/assets/javascripts/dojox/ack.js +22 -0
  33. data/vendor/assets/javascripts/dojox/dojox.require.js +5 -0
  34. data/vendor/assets/javascripts/dojox/main.js +95 -0
  35. data/vendor/assets/javascripts/dojox/reload.js +26 -0
  36. data/vendor/assets/javascripts/dojox/timestamp.js +22 -0
  37. data/vendor/assets/javascripts/dojox/timesync.js +22 -0
  38. data/vendor/assets/javascripts/jquery/.DS_Store +0 -0
  39. data/vendor/assets/javascripts/jquery/jquery.cometd-ack.js +33 -0
  40. data/vendor/assets/javascripts/jquery/jquery.cometd-reload.js +41 -0
  41. data/vendor/assets/javascripts/jquery/jquery.cometd-timestamp.js +33 -0
  42. data/vendor/assets/javascripts/jquery/jquery.cometd-timesync.js +33 -0
  43. data/vendor/assets/javascripts/jquery/jquery.cometd.js +140 -0
  44. data/vendor/assets/javascripts/jquery/jquery.cometd.require.js +5 -0
  45. 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
+ }());