Page Menu
Home
Code
Search
Configure Global Search
Log In
Files
F944768
cometd.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
18 KB
Subscribers
None
cometd.js
View Options
if
(
!
dojo
.
_hasResource
[
"dojox._cometd.cometd"
]){
//_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo
.
_hasResource
[
"dojox._cometd.cometd"
]
=
true
;
dojo
.
provide
(
"dojox._cometd.cometd"
);
dojo
.
require
(
"dojo.AdapterRegistry"
);
dojo
.
require
(
"dojo.io.script"
);
// FIXME: need to add local topic support to advise about:
// successful handshake
// network failure of channel
// graceful disconnect
/*
* this file defines Comet protocol client. Actual message transport is
* deferred to one of several connection type implementations. The default is a
* long-polling implementation. A single global object named "dojox.cometd" is
* used to mediate for these connection types in order to provide a stable
* interface.
*/
dojox
.
cometd
=
new
function
(){
/* cometd states:
* DISCONNECTED: _initialized==false && _connected==false
* CONNECTING: _initialized==true && _connected==false (handshake sent)
* CONNECTED: _initialized==true && _connected==true (first successful connect)
* DISCONNECTING: _initialized==false && _connected==true (disconnect sent)
*/
this
.
_initialized
=
false
;
this
.
_connected
=
false
;
this
.
_polling
=
false
;
this
.
connectionTypes
=
new
dojo
.
AdapterRegistry
(
true
);
this
.
version
=
"1.0"
;
this
.
minimumVersion
=
"0.9"
;
this
.
clientId
=
null
;
this
.
messageId
=
0
;
this
.
batch
=
0
;
this
.
_isXD
=
false
;
this
.
handshakeReturn
=
null
;
this
.
currentTransport
=
null
;
this
.
url
=
null
;
this
.
lastMessage
=
null
;
this
.
topics
=
{};
this
.
_messageQ
=
[];
this
.
handleAs
=
"json-comment-optional"
;
this
.
advice
;
this
.
pendingSubscriptions
=
{}
this
.
pendingUnsubscriptions
=
{}
this
.
_subscriptions
=
[];
this
.
tunnelInit
=
function
(
childLocation
,
childDomain
){
// placeholder
}
this
.
tunnelCollapse
=
function
(){
console
.
debug
(
"tunnel collapsed!"
);
// placeholder
}
this
.
init
=
function
(
root
,
props
,
bargs
){
// FIXME: if the root isn't from the same host, we should automatically
// try to select an XD-capable transport
props
=
props
||
{};
// go ask the short bus server what we can support
props
.
version
=
this
.
version
;
props
.
minimumVersion
=
this
.
minimumVersion
;
props
.
channel
=
"/meta/handshake"
;
props
.
id
=
""
+
this
.
messageId
++
;
this
.
url
=
root
||
djConfig
[
"cometdRoot"
];
if
(
!
this
.
url
){
console
.
debug
(
"no cometd root specified in djConfig and no root passed"
);
return
;
}
// Are we x-domain? borrowed from dojo.uri.Uri in lieu of fixed host and port properties
var
regexp
=
"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"
;
var
r
=
(
""
+
window
.
location
).
match
(
new
RegExp
(
regexp
));
if
(
r
[
4
]){
var
tmp
=
r
[
4
].
split
(
":"
);
var
thisHost
=
tmp
[
0
];
var
thisPort
=
tmp
[
1
]
||
"80"
;
// FIXME: match 443
r
=
this
.
url
.
match
(
new
RegExp
(
regexp
));
if
(
r
[
4
]){
tmp
=
r
[
4
].
split
(
":"
);
var
urlHost
=
tmp
[
0
];
var
urlPort
=
tmp
[
1
]
||
"80"
;
this
.
_isXD
=
((
urlHost
!=
thisHost
)
||
(
urlPort
!=
thisPort
));
}
}
if
(
!
this
.
_isXD
){
if
(
props
.
ext
){
if
(
props
.
ext
[
"json-comment-filtered"
]
!==
true
&&
props
.
ext
[
"json-comment-filtered"
]
!==
false
){
props
.
ext
[
"json-comment-filtered"
]
=
true
;
}
}
else
{
props
.
ext
=
{
"json-comment-filtered"
:
true
};
}
}
var
bindArgs
=
{
url
:
this
.
url
,
handleAs
:
this
.
handleAs
,
content
:
{
"message"
:
dojo
.
toJson
([
props
])
},
load
:
dojo
.
hitch
(
this
,
"finishInit"
),
error
:
function
(
e
){
console
.
debug
(
"handshake error!:"
,
e
);
}
};
if
(
bargs
){
dojo
.
mixin
(
bindArgs
,
bargs
);
}
this
.
_props
=
props
;
this
.
_initialized
=
true
;
this
.
batch
=
0
;
this
.
startBatch
();
// if xdomain, then we assume jsonp for handshake
if
(
this
.
_isXD
){
bindArgs
.
callbackParamName
=
"jsonp"
;
return
dojo
.
io
.
script
.
get
(
bindArgs
);
}
return
dojo
.
xhrPost
(
bindArgs
);
}
this
.
finishInit
=
function
(
data
){
data
=
data
[
0
];
this
.
handshakeReturn
=
data
;
// pick a transport
if
(
data
[
"advice"
]){
this
.
advice
=
data
.
advice
;
}
if
(
!
data
.
successful
){
console
.
debug
(
"cometd init failed"
);
if
(
this
.
advice
&&
this
.
advice
[
"reconnect"
]
==
"none"
){
return
;
}
if
(
this
.
advice
&&
this
.
advice
[
"interval"
]
&&
this
.
advice
.
interval
>
0
){
var
cometd
=
this
;
setTimeout
(
function
(){
cometd
.
init
(
cometd
.
url
,
cometd
.
_props
);
},
this
.
advice
.
interval
);
}
else
{
this
.
init
(
this
.
url
,
this
.
_props
);
}
return
;
}
if
(
data
.
version
<
this
.
minimumVersion
){
console
.
debug
(
"cometd protocol version mismatch. We wanted"
,
this
.
minimumVersion
,
"but got"
,
data
.
version
);
return
;
}
this
.
currentTransport
=
this
.
connectionTypes
.
match
(
data
.
supportedConnectionTypes
,
data
.
version
,
this
.
_isXD
);
this
.
currentTransport
.
_cometd
=
this
;
this
.
currentTransport
.
version
=
data
.
version
;
this
.
clientId
=
data
.
clientId
;
this
.
tunnelInit
=
dojo
.
hitch
(
this
.
currentTransport
,
"tunnelInit"
);
this
.
tunnelCollapse
=
dojo
.
hitch
(
this
.
currentTransport
,
"tunnelCollapse"
);
this
.
currentTransport
.
startup
(
data
);
}
// public API functions called by cometd or by the transport classes
this
.
deliver
=
function
(
messages
){
// console.debug(messages);
dojo
.
forEach
(
messages
,
this
.
_deliver
,
this
);
return
messages
;
}
this
.
_deliver
=
function
(
message
){
// dipatch events along the specified path
if
(
!
message
[
"channel"
]){
if
(
message
[
"success"
]
!==
true
){
console
.
debug
(
"cometd error: no channel for message!"
,
message
);
return
;
}
}
this
.
lastMessage
=
message
;
if
(
message
.
advice
){
this
.
advice
=
message
.
advice
;
// TODO maybe merge?
}
// check to see if we got a /meta channel message that we care about
if
(
(
message
[
"channel"
])
&&
(
message
.
channel
.
length
>
5
)
&&
(
message
.
channel
.
substr
(
0
,
5
)
==
"/meta"
)){
// check for various meta topic actions that we need to respond to
switch
(
message
.
channel
){
case
"/meta/connect"
:
if
(
message
.
successful
&&
!
this
.
_connected
){
this
.
_connected
=
this
.
_initialized
;
this
.
endBatch
();
}
else
if
(
!
this
.
_initialized
){
this
.
_connected
=
false
;
// finish disconnect
}
break
;
case
"/meta/subscribe"
:
var
pendingDef
=
this
.
pendingSubscriptions
[
message
.
subscription
];
if
(
!
message
.
successful
){
if
(
pendingDef
){
pendingDef
.
errback
(
new
Error
(
message
.
error
));
delete
this
.
pendingSubscriptions
[
message
.
subscription
];
}
return
;
}
dojox
.
cometd
.
subscribed
(
message
.
subscription
,
message
);
if
(
pendingDef
){
pendingDef
.
callback
(
true
);
delete
this
.
pendingSubscriptions
[
message
.
subscription
];
}
break
;
case
"/meta/unsubscribe"
:
var
pendingDef
=
this
.
pendingUnsubscriptions
[
message
.
subscription
];
if
(
!
message
.
successful
){
if
(
pendingDef
){
pendingDef
.
errback
(
new
Error
(
message
.
error
));
delete
this
.
pendingUnsubscriptions
[
message
.
subscription
];
}
return
;
}
this
.
unsubscribed
(
message
.
subscription
,
message
);
if
(
pendingDef
){
pendingDef
.
callback
(
true
);
delete
this
.
pendingUnsubscriptions
[
message
.
subscription
];
}
break
;
}
}
// send the message down for processing by the transport
this
.
currentTransport
.
deliver
(
message
);
if
(
message
.
data
){
// dispatch the message to any locally subscribed listeners
var
tname
=
"/cometd"
+
message
.
channel
;
dojo
.
publish
(
tname
,
[
message
]);
}
}
this
.
disconnect
=
function
(){
dojo
.
forEach
(
this
.
_subscriptions
,
dojo
.
unsubscribe
);
this
.
_subscriptions
=
[];
this
.
_messageQ
=
[];
if
(
this
.
_initialized
&&
this
.
currentTransport
){
this
.
_initialized
=
false
;
this
.
currentTransport
.
disconnect
();
}
this
.
_initialized
=
false
;
if
(
!
this
.
_polling
)
this
.
_connected
=
false
;
}
// public API functions called by end users
this
.
publish
=
function
(
/*string*/
channel
,
/*object*/
data
,
/*object*/
properties
){
// summary:
// publishes the passed message to the cometd server for delivery
// on the specified topic
// channel:
// the destination channel for the message
// data:
// a JSON object containing the message "payload"
// properties:
// Optional. Other meta-data to be mixed into the top-level of the
// message
var
message
=
{
data
:
data
,
channel
:
channel
};
if
(
properties
){
dojo
.
mixin
(
message
,
properties
);
}
this
.
_sendMessage
(
message
);
}
this
.
_sendMessage
=
function
(
/* object */
message
){
if
(
this
.
currentTransport
&&
this
.
_connected
&&
this
.
batch
==
0
){
return
this
.
currentTransport
.
sendMessages
([
message
]);
}
else
{
this
.
_messageQ
.
push
(
message
);
}
}
this
.
subscribe
=
function
(
/*string */
channel
,
/*object, optional*/
objOrFunc
,
/*string, optional*/
funcName
){
// return: boolean
// summary:
// inform the server of this client's interest in channel
// channel:
// name of the cometd channel to subscribe to
// objOrFunc:
// an object scope for funcName or the name or reference to a
// function to be called when messages are delivered to the
// channel
// funcName:
// the second half of the objOrFunc/funcName pair for identifying
// a callback function to notifiy upon channel message delivery
if
(
this
.
pendingSubscriptions
[
channel
]){
// We already asked to subscribe to this channel, and
// haven't heard back yet. Fail the previous attempt.
var
oldDef
=
this
.
pendingSubscriptions
[
channel
];
oldDef
.
cancel
();
delete
this
.
pendingSubscriptions
[
channel
];
}
var
pendingDef
=
new
dojo
.
Deferred
();
this
.
pendingSubscriptions
[
channel
]
=
pendingDef
;
if
(
objOrFunc
){
var
tname
=
"/cometd"
+
channel
;
if
(
this
.
topics
[
tname
]){
dojo
.
unsubscribe
(
this
.
topics
[
tname
]);
}
var
topic
=
dojo
.
subscribe
(
tname
,
objOrFunc
,
funcName
);
this
.
topics
[
tname
]
=
topic
;
}
this
.
_sendMessage
({
channel
:
"/meta/subscribe"
,
subscription
:
channel
});
return
pendingDef
;
}
this
.
subscribed
=
function
(
/*string*/
channel
,
/*obj*/
message
){
}
this
.
unsubscribe
=
function
(
/*string*/
channel
){
// return: boolean
// summary:
// inform the server of this client's disinterest in channel
// channel:
// name of the cometd channel to unsubscribe from
if
(
this
.
pendingUnsubscriptions
[
channel
]){
// We already asked to unsubscribe from this channel, and
// haven't heard back yet. Fail the previous attempt.
var
oldDef
=
this
.
pendingUnsubscriptions
[
channel
];
oldDef
.
cancel
();
delete
this
.
pendingUnsubscriptions
[
channel
];
}
var
pendingDef
=
new
dojo
.
Deferred
();
this
.
pendingUnsubscriptions
[
channel
]
=
pendingDef
;
var
tname
=
"/cometd"
+
channel
;
if
(
this
.
topics
[
tname
]){
dojo
.
unsubscribe
(
this
.
topics
[
tname
]);
}
this
.
_sendMessage
({
channel
:
"/meta/unsubscribe"
,
subscription
:
channel
});
return
pendingDef
;
}
this
.
unsubscribed
=
function
(
/*string*/
channel
,
/*obj*/
message
){
}
this
.
startBatch
=
function
(){
this
.
batch
++
;
}
this
.
endBatch
=
function
(){
if
(
--
this
.
batch
<=
0
&&
this
.
currentTransport
&&
this
.
_connected
){
this
.
batch
=
0
;
var
messages
=
this
.
_messageQ
;
this
.
_messageQ
=
[];
if
(
messages
.
length
>
0
){
this
.
currentTransport
.
sendMessages
(
messages
);
}
}
}
this
.
_onUnload
=
function
(){
// make this the last of the onUnload method
dojo
.
addOnUnload
(
dojox
.
cometd
,
"disconnect"
);
}
}
/*
transport objects MUST expose the following methods:
- check
- startup
- sendMessages
- deliver
- disconnect
optional, standard but transport dependent methods are:
- tunnelCollapse
- tunnelInit
Transports SHOULD be namespaced under the cometd object and transports MUST
register themselves with cometd.connectionTypes
here's a stub transport defintion:
cometd.blahTransport = new function(){
this._connectionType="my-polling";
this._cometd=null;
this.lastTimestamp = null;
this.check = function(types, version, xdomain){
// summary:
// determines whether or not this transport is suitable given a
// list of transport types that the server supports
return dojo.lang.inArray(types, "blah");
}
this.startup = function(){
if(dojox.cometd._polling){ return; }
// FIXME: fill in startup routine here
dojox.cometd._polling = true;
}
this.sendMessages = function(message){
// FIXME: fill in message array sending logic
}
this.deliver = function(message){
if(message["timestamp"]){
this.lastTimestamp = message.timestamp;
}
if( (message.channel.length > 5)&&
(message.channel.substr(0, 5) == "/meta")){
// check for various meta topic actions that we need to respond to
// switch(message.channel){
// case "/meta/connect":
// // FIXME: fill in logic here
// break;
// // case ...: ...
// }
}
}
this.disconnect = function(){
}
}
cometd.connectionTypes.register("blah", cometd.blahTransport.check, cometd.blahTransport);
*/
dojox
.
cometd
.
longPollTransport
=
new
function
(){
this
.
_connectionType
=
"long-polling"
;
this
.
_cometd
=
null
;
this
.
lastTimestamp
=
null
;
this
.
check
=
function
(
types
,
version
,
xdomain
){
return
((
!
xdomain
)
&&
(
dojo
.
indexOf
(
types
,
"long-polling"
)
>=
0
));
}
this
.
tunnelInit
=
function
(){
if
(
this
.
_cometd
.
_polling
){
return
;
}
this
.
openTunnelWith
({
message
:
dojo
.
toJson
([
{
channel
:
"/meta/connect"
,
clientId
:
this
.
_cometd
.
clientId
,
connectionType
:
this
.
_connectionType
,
id
:
""
+
this
.
_cometd
.
messageId
++
}
])
});
}
this
.
tunnelCollapse
=
function
(){
if
(
!
this
.
_cometd
.
_polling
){
// try to restart the tunnel
this
.
_cometd
.
_polling
=
false
;
// TODO handle transport specific advice
if
(
this
.
_cometd
[
"advice"
]){
if
(
this
.
_cometd
.
advice
[
"reconnect"
]
==
"none"
){
return
;
}
if
(
(
this
.
_cometd
.
advice
[
"interval"
])
&&
(
this
.
_cometd
.
advice
.
interval
>
0
)
){
var
transport
=
this
;
setTimeout
(
function
(){
transport
.
_connect
();
},
this
.
_cometd
.
advice
.
interval
);
}
else
{
this
.
_connect
();
}
}
else
{
this
.
_connect
();
}
}
}
this
.
_connect
=
function
(){
if
(
(
this
.
_cometd
[
"advice"
])
&&
(
this
.
_cometd
.
advice
[
"reconnect"
]
==
"handshake"
)
){
this
.
_cometd
.
init
(
this
.
_cometd
.
url
,
this
.
_cometd
.
_props
);
}
else
if
(
this
.
_cometd
.
_connected
){
this
.
openTunnelWith
({
message
:
dojo
.
toJson
([
{
channel
:
"/meta/connect"
,
connectionType
:
this
.
_connectionType
,
clientId
:
this
.
_cometd
.
clientId
,
timestamp
:
this
.
lastTimestamp
,
id
:
""
+
this
.
_cometd
.
messageId
++
}
])
});
}
}
this
.
deliver
=
function
(
message
){
// console.debug(message);
if
(
message
[
"timestamp"
]){
this
.
lastTimestamp
=
message
.
timestamp
;
}
}
this
.
openTunnelWith
=
function
(
content
,
url
){
// console.debug("openTunnelWith:", content, (url||cometd.url));
var
d
=
dojo
.
xhrPost
({
url
:
(
url
||
this
.
_cometd
.
url
),
content
:
content
,
handleAs
:
this
.
_cometd
.
handleAs
,
load
:
dojo
.
hitch
(
this
,
function
(
data
){
// console.debug(evt.responseText);
// console.debug(data);
this
.
_cometd
.
_polling
=
false
;
this
.
_cometd
.
deliver
(
data
);
this
.
tunnelCollapse
();
}),
error
:
function
(
err
){
console
.
debug
(
"tunnel opening failed:"
,
err
);
dojo
.
cometd
.
_polling
=
false
;
// TODO - follow advice to reconnect or rehandshake?
}
});
this
.
_cometd
.
_polling
=
true
;
}
this
.
sendMessages
=
function
(
messages
){
for
(
var
i
=
0
;
i
<
messages
.
length
;
i
++
){
messages
[
i
].
clientId
=
this
.
_cometd
.
clientId
;
messages
[
i
].
id
=
""
+
this
.
_cometd
.
messageId
++
;
}
return
dojo
.
xhrPost
({
url
:
this
.
_cometd
.
url
||
djConfig
[
"cometdRoot"
],
handleAs
:
this
.
_cometd
.
handleAs
,
load
:
dojo
.
hitch
(
this
.
_cometd
,
"deliver"
),
content
:
{
message
:
dojo
.
toJson
(
messages
)
}
});
}
this
.
startup
=
function
(
handshakeData
){
if
(
this
.
_cometd
.
_connected
){
return
;
}
this
.
tunnelInit
();
}
this
.
disconnect
=
function
(){
dojo
.
xhrPost
({
url
:
this
.
_cometd
.
url
||
djConfig
[
"cometdRoot"
],
handleAs
:
this
.
_cometd
.
handleAs
,
content
:
{
message
:
dojo
.
toJson
([{
channel
:
"/meta/disconnect"
,
clientId
:
this
.
_cometd
.
clientId
,
id
:
""
+
this
.
_cometd
.
messageId
++
}])
}
});
}
}
dojox
.
cometd
.
callbackPollTransport
=
new
function
(){
this
.
_connectionType
=
"callback-polling"
;
this
.
_cometd
=
null
;
this
.
lastTimestamp
=
null
;
this
.
check
=
function
(
types
,
version
,
xdomain
){
// we handle x-domain!
return
(
dojo
.
indexOf
(
types
,
"callback-polling"
)
>=
0
);
}
this
.
tunnelInit
=
function
(){
if
(
this
.
_cometd
.
_polling
){
return
;
}
this
.
openTunnelWith
({
message
:
dojo
.
toJson
([
{
channel
:
"/meta/connect"
,
clientId
:
this
.
_cometd
.
clientId
,
connectionType
:
this
.
_connectionType
,
id
:
""
+
this
.
_cometd
.
messageId
++
}
])
});
}
this
.
tunnelCollapse
=
dojox
.
cometd
.
longPollTransport
.
tunnelCollapse
;
this
.
_connect
=
dojox
.
cometd
.
longPollTransport
.
_connect
;
this
.
deliver
=
dojox
.
cometd
.
longPollTransport
.
deliver
;
this
.
openTunnelWith
=
function
(
content
,
url
){
// create a <script> element to generate the request
dojo
.
io
.
script
.
get
({
load
:
dojo
.
hitch
(
this
,
function
(
data
){
this
.
_cometd
.
_polling
=
false
;
this
.
_cometd
.
deliver
(
data
);
this
.
tunnelCollapse
();
}),
error
:
function
(){
this
.
_cometd
.
_polling
=
false
;
console
.
debug
(
"tunnel opening failed"
);
},
url
:
(
url
||
this
.
_cometd
.
url
),
content
:
content
,
callbackParamName
:
"jsonp"
});
this
.
_cometd
.
_polling
=
true
;
}
this
.
sendMessages
=
function
(
/*array*/
messages
){
for
(
var
i
=
0
;
i
<
messages
.
length
;
i
++
){
messages
[
i
].
clientId
=
this
.
_cometd
.
clientId
;
messages
[
i
].
id
=
""
+
this
.
_cometd
.
messageId
++
;
}
var
bindArgs
=
{
url
:
this
.
_cometd
.
url
||
djConfig
[
"cometdRoot"
],
load
:
dojo
.
hitch
(
this
.
_cometd
,
"deliver"
),
callbackParamName
:
"jsonp"
,
content
:
{
message
:
dojo
.
toJson
(
messages
)
}
};
return
dojo
.
io
.
script
.
get
(
bindArgs
);
}
this
.
startup
=
function
(
handshakeData
){
if
(
this
.
_cometd
.
_connected
){
return
;
}
this
.
tunnelInit
();
}
this
.
disconnect
=
dojox
.
cometd
.
longPollTransport
.
disconnect
;
this
.
disconnect
=
function
(){
dojo
.
io
.
script
.
get
({
url
:
this
.
_cometd
.
url
||
djConfig
[
"cometdRoot"
],
callbackParamName
:
"jsonp"
,
content
:
{
message
:
dojo
.
toJson
([{
channel
:
"/meta/disconnect"
,
clientId
:
this
.
_cometd
.
clientId
,
id
:
""
+
this
.
_cometd
.
messageId
++
}])
}
});
}
}
dojox
.
cometd
.
connectionTypes
.
register
(
"long-polling"
,
dojox
.
cometd
.
longPollTransport
.
check
,
dojox
.
cometd
.
longPollTransport
);
dojox
.
cometd
.
connectionTypes
.
register
(
"callback-polling"
,
dojox
.
cometd
.
callbackPollTransport
.
check
,
dojox
.
cometd
.
callbackPollTransport
);
dojo
.
addOnUnload
(
dojox
.
cometd
,
"_onUnload"
);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 25, 23:28 (1 w, 15 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
22355
Default Alt Text
cometd.js (18 KB)
Attached To
rZED Zed
Event Timeline
Log In to Comment