cometd.js
上传用户:kimgenplus
上传日期:2016-06-05
资源大小:20877k
文件大小:18k
源码类别:

OA系统

开发平台:

Java

  1. /*
  2. Copyright (c) 2004-2006, The Dojo Foundation
  3. All Rights Reserved.
  4. Licensed under the Academic Free License version 2.1 or above OR the
  5. modified BSD license. For more information on Dojo licensing, see:
  6. http://dojotoolkit.org/community/licensing.shtml
  7. */
  8. dojo.require("dojo.io.common");
  9. dojo.provide("dojo.io.cometd");
  10. dojo.require("dojo.AdapterRegistry");
  11. dojo.require("dojo.json");
  12. dojo.require("dojo.io.BrowserIO");
  13. dojo.require("dojo.io.IframeIO");
  14. dojo.require("dojo.io.ScriptSrcIO");
  15. dojo.require("dojo.io.cookie");
  16. dojo.require("dojo.event.*");
  17. dojo.require("dojo.lang.common");
  18. dojo.require("dojo.lang.func");
  19. cometd = new function () {
  20. this.initialized = false;
  21. this.connected = false;
  22. this.connectionTypes = new dojo.AdapterRegistry(true);
  23. this.version = 0.1;
  24. this.minimumVersion = 0.1;
  25. this.clientId = null;
  26. this._isXD = false;
  27. this.handshakeReturn = null;
  28. this.currentTransport = null;
  29. this.url = null;
  30. this.lastMessage = null;
  31. this.globalTopicChannels = {};
  32. this.backlog = [];
  33. this.tunnelInit = function (childLocation, childDomain) {
  34. };
  35. this.tunnelCollapse = function () {
  36. dojo.debug("tunnel collapsed!");
  37. };
  38. this.init = function (props, root, bargs) {
  39. props = props || {};
  40. props.version = this.version;
  41. props.minimumVersion = this.minimumVersion;
  42. props.channel = "/meta/handshake";
  43. this.url = root || djConfig["cometdRoot"];
  44. if (!this.url) {
  45. dojo.debug("no cometd root specified in djConfig and no root passed");
  46. return;
  47. }
  48. var bindArgs = {url:this.url, method:"POST", mimetype:"text/json", load:dojo.lang.hitch(this, "finishInit"), content:{"message":dojo.json.serialize([props])}};
  49. var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$";
  50. var r = ("" + window.location).match(new RegExp(regexp));
  51. if (r[4]) {
  52. var tmp = r[4].split(":");
  53. var thisHost = tmp[0];
  54. var thisPort = tmp[1] || "80";
  55. r = this.url.match(new RegExp(regexp));
  56. if (r[4]) {
  57. tmp = r[4].split(":");
  58. var urlHost = tmp[0];
  59. var urlPort = tmp[1] || "80";
  60. if ((urlHost != thisHost) || (urlPort != thisPort)) {
  61. dojo.debug(thisHost, urlHost);
  62. dojo.debug(thisPort, urlPort);
  63. this._isXD = true;
  64. bindArgs.transport = "ScriptSrcTransport";
  65. bindArgs.jsonParamName = "jsonp";
  66. bindArgs.method = "GET";
  67. }
  68. }
  69. }
  70. if (bargs) {
  71. dojo.lang.mixin(bindArgs, bargs);
  72. }
  73. return dojo.io.bind(bindArgs);
  74. };
  75. this.finishInit = function (type, data, evt, request) {
  76. data = data[0];
  77. this.handshakeReturn = data;
  78. if (data["authSuccessful"] == false) {
  79. dojo.debug("cometd authentication failed");
  80. return;
  81. }
  82. if (data.version < this.minimumVersion) {
  83. dojo.debug("cometd protocol version mismatch. We wanted", this.minimumVersion, "but got", data.version);
  84. return;
  85. }
  86. this.currentTransport = this.connectionTypes.match(data.supportedConnectionTypes, data.version, this._isXD);
  87. this.currentTransport.version = data.version;
  88. this.clientId = data.clientId;
  89. this.tunnelInit = dojo.lang.hitch(this.currentTransport, "tunnelInit");
  90. this.tunnelCollapse = dojo.lang.hitch(this.currentTransport, "tunnelCollapse");
  91. this.initialized = true;
  92. this.currentTransport.startup(data);
  93. while (this.backlog.length != 0) {
  94. var cur = this.backlog.shift();
  95. var fn = cur.shift();
  96. this[fn].apply(this, cur);
  97. }
  98. };
  99. this._getRandStr = function () {
  100. return Math.random().toString().substring(2, 10);
  101. };
  102. this.deliver = function (messages) {
  103. dojo.lang.forEach(messages, this._deliver, this);
  104. };
  105. this._deliver = function (message) {
  106. if (!message["channel"]) {
  107. dojo.debug("cometd error: no channel for message!");
  108. return;
  109. }
  110. if (!this.currentTransport) {
  111. this.backlog.push(["deliver", message]);
  112. return;
  113. }
  114. this.lastMessage = message;
  115. if ((message.channel.length > 5) && (message.channel.substr(0, 5) == "/meta")) {
  116. switch (message.channel) {
  117.   case "/meta/subscribe":
  118. if (!message.successful) {
  119. dojo.debug("cometd subscription error for channel", message.channel, ":", message.error);
  120. return;
  121. }
  122. this.subscribed(message.subscription, message);
  123. break;
  124.   case "/meta/unsubscribe":
  125. if (!message.successful) {
  126. dojo.debug("cometd unsubscription error for channel", message.channel, ":", message.error);
  127. return;
  128. }
  129. this.unsubscribed(message.subscription, message);
  130. break;
  131. }
  132. }
  133. this.currentTransport.deliver(message);
  134. if (message.data) {
  135. var tname = (this.globalTopicChannels[message.channel]) ? message.channel : "/cometd" + message.channel;
  136. dojo.event.topic.publish(tname, message);
  137. }
  138. };
  139. this.disconnect = function () {
  140. if (!this.currentTransport) {
  141. dojo.debug("no current transport to disconnect from");
  142. return;
  143. }
  144. this.currentTransport.disconnect();
  145. };
  146. this.publish = function (channel, data, properties) {
  147. if (!this.currentTransport) {
  148. this.backlog.push(["publish", channel, data, properties]);
  149. return;
  150. }
  151. var message = {data:data, channel:channel};
  152. if (properties) {
  153. dojo.lang.mixin(message, properties);
  154. }
  155. return this.currentTransport.sendMessage(message);
  156. };
  157. this.subscribe = function (channel, useLocalTopics, objOrFunc, funcName) {
  158. if (!this.currentTransport) {
  159. this.backlog.push(["subscribe", channel, useLocalTopics, objOrFunc, funcName]);
  160. return;
  161. }
  162. if (objOrFunc) {
  163. var tname = (useLocalTopics) ? channel : "/cometd" + channel;
  164. if (useLocalTopics) {
  165. this.globalTopicChannels[channel] = true;
  166. }
  167. dojo.event.topic.subscribe(tname, objOrFunc, funcName);
  168. }
  169. return this.currentTransport.sendMessage({channel:"/meta/subscribe", subscription:channel});
  170. };
  171. this.subscribed = function (channel, message) {
  172. dojo.debug(channel);
  173. dojo.debugShallow(message);
  174. };
  175. this.unsubscribe = function (channel, useLocalTopics, objOrFunc, funcName) {
  176. if (!this.currentTransport) {
  177. this.backlog.push(["unsubscribe", channel, useLocalTopics, objOrFunc, funcName]);
  178. return;
  179. }
  180. if (objOrFunc) {
  181. var tname = (useLocalTopics) ? channel : "/cometd" + channel;
  182. dojo.event.topic.unsubscribe(tname, objOrFunc, funcName);
  183. }
  184. return this.currentTransport.sendMessage({channel:"/meta/unsubscribe", subscription:channel});
  185. };
  186. this.unsubscribed = function (channel, message) {
  187. dojo.debug(channel);
  188. dojo.debugShallow(message);
  189. };
  190. };
  191. cometd.iframeTransport = new function () {
  192. this.connected = false;
  193. this.connectionId = null;
  194. this.rcvNode = null;
  195. this.rcvNodeName = "";
  196. this.phonyForm = null;
  197. this.authToken = null;
  198. this.lastTimestamp = null;
  199. this.lastId = null;
  200. this.backlog = [];
  201. this.check = function (types, version, xdomain) {
  202. return ((!xdomain) && (!dojo.render.html.safari) && (dojo.lang.inArray(types, "iframe")));
  203. };
  204. this.tunnelInit = function () {
  205. this.postToIframe({message:dojo.json.serialize([{channel:"/meta/connect", clientId:cometd.clientId, connectionType:"iframe"}])});
  206. };
  207. this.tunnelCollapse = function () {
  208. if (this.connected) {
  209. this.connected = false;
  210. this.postToIframe({message:dojo.json.serialize([{channel:"/meta/reconnect", clientId:cometd.clientId, connectionId:this.connectionId, timestamp:this.lastTimestamp, id:this.lastId}])});
  211. }
  212. };
  213. this.deliver = function (message) {
  214. if (message["timestamp"]) {
  215. this.lastTimestamp = message.timestamp;
  216. }
  217. if (message["id"]) {
  218. this.lastId = message.id;
  219. }
  220. if ((message.channel.length > 5) && (message.channel.substr(0, 5) == "/meta")) {
  221. switch (message.channel) {
  222.   case "/meta/connect":
  223. if (!message.successful) {
  224. dojo.debug("cometd connection error:", message.error);
  225. return;
  226. }
  227. this.connectionId = message.connectionId;
  228. this.connected = true;
  229. this.processBacklog();
  230. break;
  231.   case "/meta/reconnect":
  232. if (!message.successful) {
  233. dojo.debug("cometd reconnection error:", message.error);
  234. return;
  235. }
  236. this.connected = true;
  237. break;
  238.   case "/meta/subscribe":
  239. if (!message.successful) {
  240. dojo.debug("cometd subscription error for channel", message.channel, ":", message.error);
  241. return;
  242. }
  243. dojo.debug(message.channel);
  244. break;
  245. }
  246. }
  247. };
  248. this.widenDomain = function (domainStr) {
  249. var cd = domainStr || document.domain;
  250. if (cd.indexOf(".") == -1) {
  251. return;
  252. }
  253. var dps = cd.split(".");
  254. if (dps.length <= 2) {
  255. return;
  256. }
  257. dps = dps.slice(dps.length - 2);
  258. document.domain = dps.join(".");
  259. return document.domain;
  260. };
  261. this.postToIframe = function (content, url) {
  262. if (!this.phonyForm) {
  263. if (dojo.render.html.ie) {
  264. this.phonyForm = document.createElement("<form enctype='application/x-www-form-urlencoded' method='POST' style='display: none;'>");
  265. dojo.body().appendChild(this.phonyForm);
  266. } else {
  267. this.phonyForm = document.createElement("form");
  268. this.phonyForm.style.display = "none";
  269. dojo.body().appendChild(this.phonyForm);
  270. this.phonyForm.enctype = "application/x-www-form-urlencoded";
  271. this.phonyForm.method = "POST";
  272. }
  273. }
  274. this.phonyForm.action = url || cometd.url;
  275. this.phonyForm.target = this.rcvNodeName;
  276. this.phonyForm.setAttribute("target", this.rcvNodeName);
  277. while (this.phonyForm.firstChild) {
  278. this.phonyForm.removeChild(this.phonyForm.firstChild);
  279. }
  280. for (var x in content) {
  281. var tn;
  282. if (dojo.render.html.ie) {
  283. tn = document.createElement("<input type='hidden' name='" + x + "' value='" + content[x] + "'>");
  284. this.phonyForm.appendChild(tn);
  285. } else {
  286. tn = document.createElement("input");
  287. this.phonyForm.appendChild(tn);
  288. tn.type = "hidden";
  289. tn.name = x;
  290. tn.value = content[x];
  291. }
  292. }
  293. this.phonyForm.submit();
  294. };
  295. this.processBacklog = function () {
  296. while (this.backlog.length > 0) {
  297. this.sendMessage(this.backlog.shift(), true);
  298. }
  299. };
  300. this.sendMessage = function (message, bypassBacklog) {
  301. if ((bypassBacklog) || (this.connected)) {
  302. message.connectionId = this.connectionId;
  303. message.clientId = cometd.clientId;
  304. var bindArgs = {url:cometd.url || djConfig["cometdRoot"], method:"POST", mimetype:"text/json", content:{message:dojo.json.serialize([message])}};
  305. return dojo.io.bind(bindArgs);
  306. } else {
  307. this.backlog.push(message);
  308. }
  309. };
  310. this.startup = function (handshakeData) {
  311. dojo.debug("startup!");
  312. dojo.debug(dojo.json.serialize(handshakeData));
  313. if (this.connected) {
  314. return;
  315. }
  316. this.rcvNodeName = "cometdRcv_" + cometd._getRandStr();
  317. var initUrl = cometd.url + "/?tunnelInit=iframe";
  318. if (false && dojo.render.html.ie) {
  319. this.rcvNode = new ActiveXObject("htmlfile");
  320. this.rcvNode.open();
  321. this.rcvNode.write("<html>");
  322. this.rcvNode.write("<script>document.domain = '" + document.domain + "'");
  323. this.rcvNode.write("</html>");
  324. this.rcvNode.close();
  325. var ifrDiv = this.rcvNode.createElement("div");
  326. this.rcvNode.appendChild(ifrDiv);
  327. this.rcvNode.parentWindow.dojo = dojo;
  328. ifrDiv.innerHTML = "<iframe src='" + initUrl + "'></iframe>";
  329. } else {
  330. this.rcvNode = dojo.io.createIFrame(this.rcvNodeName, "", initUrl);
  331. }
  332. };
  333. };
  334. cometd.mimeReplaceTransport = new function () {
  335. this.connected = false;
  336. this.connectionId = null;
  337. this.xhr = null;
  338. this.authToken = null;
  339. this.lastTimestamp = null;
  340. this.lastId = null;
  341. this.backlog = [];
  342. this.check = function (types, version, xdomain) {
  343. return ((!xdomain) && (dojo.render.html.mozilla) && (dojo.lang.inArray(types, "mime-message-block")));
  344. };
  345. this.tunnelInit = function () {
  346. if (this.connected) {
  347. return;
  348. }
  349. this.openTunnelWith({message:dojo.json.serialize([{channel:"/meta/connect", clientId:cometd.clientId, connectionType:"mime-message-block"}])});
  350. this.connected = true;
  351. };
  352. this.tunnelCollapse = function () {
  353. if (this.connected) {
  354. this.connected = false;
  355. this.openTunnelWith({message:dojo.json.serialize([{channel:"/meta/reconnect", clientId:cometd.clientId, connectionId:this.connectionId, timestamp:this.lastTimestamp, id:this.lastId}])});
  356. }
  357. };
  358. this.deliver = cometd.iframeTransport.deliver;
  359. this.handleOnLoad = function (resp) {
  360. cometd.deliver(dojo.json.evalJson(this.xhr.responseText));
  361. };
  362. this.openTunnelWith = function (content, url) {
  363. this.xhr = dojo.hostenv.getXmlhttpObject();
  364. this.xhr.multipart = true;
  365. if (dojo.render.html.mozilla) {
  366. this.xhr.addEventListener("load", dojo.lang.hitch(this, "handleOnLoad"), false);
  367. } else {
  368. if (dojo.render.html.safari) {
  369. dojo.debug("Webkit is broken with multipart responses over XHR = (");
  370. this.xhr.onreadystatechange = dojo.lang.hitch(this, "handleOnLoad");
  371. } else {
  372. this.xhr.onload = dojo.lang.hitch(this, "handleOnLoad");
  373. }
  374. }
  375. this.xhr.open("POST", (url || cometd.url), true);
  376. this.xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  377. dojo.debug(dojo.json.serialize(content));
  378. this.xhr.send(dojo.io.argsFromMap(content, "utf8"));
  379. };
  380. this.processBacklog = function () {
  381. while (this.backlog.length > 0) {
  382. this.sendMessage(this.backlog.shift(), true);
  383. }
  384. };
  385. this.sendMessage = function (message, bypassBacklog) {
  386. if ((bypassBacklog) || (this.connected)) {
  387. message.connectionId = this.connectionId;
  388. message.clientId = cometd.clientId;
  389. var bindArgs = {url:cometd.url || djConfig["cometdRoot"], method:"POST", mimetype:"text/json", content:{message:dojo.json.serialize([message])}};
  390. return dojo.io.bind(bindArgs);
  391. } else {
  392. this.backlog.push(message);
  393. }
  394. };
  395. this.startup = function (handshakeData) {
  396. dojo.debugShallow(handshakeData);
  397. if (this.connected) {
  398. return;
  399. }
  400. this.tunnelInit();
  401. };
  402. };
  403. cometd.longPollTransport = new function () {
  404. this.connected = false;
  405. this.connectionId = null;
  406. this.authToken = null;
  407. this.lastTimestamp = null;
  408. this.lastId = null;
  409. this.backlog = [];
  410. this.check = function (types, version, xdomain) {
  411. return ((!xdomain) && (dojo.lang.inArray(types, "long-polling")));
  412. };
  413. this.tunnelInit = function () {
  414. if (this.connected) {
  415. return;
  416. }
  417. this.openTunnelWith({message:dojo.json.serialize([{channel:"/meta/connect", clientId:cometd.clientId, connectionType:"long-polling"}])});
  418. this.connected = true;
  419. };
  420. this.tunnelCollapse = function () {
  421. if (!this.connected) {
  422. this.connected = false;
  423. dojo.debug("clientId:", cometd.clientId);
  424. this.openTunnelWith({message:dojo.json.serialize([{channel:"/meta/reconnect", connectionType:"long-polling", clientId:cometd.clientId, connectionId:this.connectionId, timestamp:this.lastTimestamp, id:this.lastId}])});
  425. }
  426. };
  427. this.deliver = cometd.iframeTransport.deliver;
  428. this.openTunnelWith = function (content, url) {
  429. dojo.io.bind({url:(url || cometd.url), method:"post", content:content, mimetype:"text/json", load:dojo.lang.hitch(this, function (type, data, evt, args) {
  430. cometd.deliver(data);
  431. this.connected = false;
  432. this.tunnelCollapse();
  433. }), error:function () {
  434. dojo.debug("tunnel opening failed");
  435. }});
  436. this.connected = true;
  437. };
  438. this.processBacklog = function () {
  439. while (this.backlog.length > 0) {
  440. this.sendMessage(this.backlog.shift(), true);
  441. }
  442. };
  443. this.sendMessage = function (message, bypassBacklog) {
  444. if ((bypassBacklog) || (this.connected)) {
  445. message.connectionId = this.connectionId;
  446. message.clientId = cometd.clientId;
  447. var bindArgs = {url:cometd.url || djConfig["cometdRoot"], method:"post", mimetype:"text/json", content:{message:dojo.json.serialize([message])}, load:dojo.lang.hitch(this, function (type, data, evt, args) {
  448. cometd.deliver(data);
  449. })};
  450. return dojo.io.bind(bindArgs);
  451. } else {
  452. this.backlog.push(message);
  453. }
  454. };
  455. this.startup = function (handshakeData) {
  456. if (this.connected) {
  457. return;
  458. }
  459. this.tunnelInit();
  460. };
  461. };
  462. cometd.callbackPollTransport = new function () {
  463. this.connected = false;
  464. this.connectionId = null;
  465. this.authToken = null;
  466. this.lastTimestamp = null;
  467. this.lastId = null;
  468. this.backlog = [];
  469. this.check = function (types, version, xdomain) {
  470. return dojo.lang.inArray(types, "callback-polling");
  471. };
  472. this.tunnelInit = function () {
  473. if (this.connected) {
  474. return;
  475. }
  476. this.openTunnelWith({message:dojo.json.serialize([{channel:"/meta/connect", clientId:cometd.clientId, connectionType:"callback-polling"}])});
  477. this.connected = true;
  478. };
  479. this.tunnelCollapse = function () {
  480. if (!this.connected) {
  481. this.connected = false;
  482. this.openTunnelWith({message:dojo.json.serialize([{channel:"/meta/reconnect", connectionType:"long-polling", clientId:cometd.clientId, connectionId:this.connectionId, timestamp:this.lastTimestamp, id:this.lastId}])});
  483. }
  484. };
  485. this.deliver = cometd.iframeTransport.deliver;
  486. this.openTunnelWith = function (content, url) {
  487. var req = dojo.io.bind({url:(url || cometd.url), content:content, mimetype:"text/json", transport:"ScriptSrcTransport", jsonParamName:"jsonp", load:dojo.lang.hitch(this, function (type, data, evt, args) {
  488. cometd.deliver(data);
  489. this.connected = false;
  490. this.tunnelCollapse();
  491. }), error:function () {
  492. dojo.debug("tunnel opening failed");
  493. }});
  494. this.connected = true;
  495. };
  496. this.processBacklog = function () {
  497. while (this.backlog.length > 0) {
  498. this.sendMessage(this.backlog.shift(), true);
  499. }
  500. };
  501. this.sendMessage = function (message, bypassBacklog) {
  502. if ((bypassBacklog) || (this.connected)) {
  503. message.connectionId = this.connectionId;
  504. message.clientId = cometd.clientId;
  505. var bindArgs = {url:cometd.url || djConfig["cometdRoot"], mimetype:"text/json", transport:"ScriptSrcTransport", jsonParamName:"jsonp", content:{message:dojo.json.serialize([message])}, load:dojo.lang.hitch(this, function (type, data, evt, args) {
  506. cometd.deliver(data);
  507. })};
  508. return dojo.io.bind(bindArgs);
  509. } else {
  510. this.backlog.push(message);
  511. }
  512. };
  513. this.startup = function (handshakeData) {
  514. if (this.connected) {
  515. return;
  516. }
  517. this.tunnelInit();
  518. };
  519. };
  520. cometd.connectionTypes.register("mime-message-block", cometd.mimeReplaceTransport.check, cometd.mimeReplaceTransport);
  521. cometd.connectionTypes.register("long-polling", cometd.longPollTransport.check, cometd.longPollTransport);
  522. cometd.connectionTypes.register("callback-polling", cometd.callbackPollTransport.check, cometd.callbackPollTransport);
  523. cometd.connectionTypes.register("iframe", cometd.iframeTransport.check, cometd.iframeTransport);
  524. dojo.io.cometd = cometd;