Connection.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource['dojox.atom.io.Connection']){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource['dojox.atom.io.Connection'] = true;
  8. dojo.provide('dojox.atom.io.Connection');
  9. dojo.require('dojox.atom.io.model');
  10. dojo.declare("dojox.atom.io.Connection",null,{
  11. // summary: This object implements a transport layer for working with ATOM feeds and ATOM publishing protocols.
  12. // description: This object implements a transport layer for working with ATOM feeds and ATOM publishing protocols.
  13. // Specifically, it provides a mechanism by which feeds can be fetched and entries can be fetched, created
  14. // deleted, and modified. It also provides access to the introspection data.
  15. constructor: function(/* Boolean */sync, /* Boolean */preventCache){
  16. // summary:
  17. // initializer
  18. this.sync = sync;
  19. this.preventCache = preventCache;
  20. },
  21. preventCache: false, //Flag to denote if the instance should use the xhr prevent cache mechanism
  22. alertsEnabled: false, //Flag to turn on alerts instead of throwing errors.
  23. getFeed: function(/*String*/url, /*Function*/callback, /*Function*/errorCallback, scope){
  24. // summary:
  25. // Function to obtain a s specific ATOM feed from a given ATOM Feed url.
  26. // description:
  27. // This function takes the URL for a specific ATOM feed and returns
  28. // the data from that feed to the caller through the use of a callback
  29. // handler.
  30. //
  31. // url: String
  32. // The URL of the ATOM feed to fetch.
  33. // callback:
  34. // Function
  35. // A function reference that will handle the feed when it has been retrieved.
  36. // The callback should accept two parameters: The feed object and the original complete DOM object.
  37. // scope: Object
  38. // The scope to use for all callbacks.
  39. //
  40. // returns:
  41. // Nothing. The return is handled through the callback handler.
  42. this._getXmlDoc(url, "feed", new dojox.atom.io.model.Feed(), dojox.atom.io.model._Constants.ATOM_NS, callback, /*handleDocumentRetrieved,*/ errorCallback, scope);
  43. },
  44. getService: function(url, callback, errorCallback, scope){
  45. // summary:
  46. // Function to retrieve an introspection document from the given URL.
  47. // description:
  48. // This function takes the URL for an ATOM item and feed and returns
  49. // the introspection document.
  50. //
  51. // url:
  52. // String
  53. // The URL of the ATOM document to obtain the introspection document of.
  54. // callback:
  55. // Function
  56. // A function reference that will handle the introspection document when it has been retrieved.
  57. // The callback should accept two parameters: The introspection document object and the original complete DOM object.
  58. //
  59. // returns:
  60. // Nothing. The return is handled through the callback handler.
  61. this._getXmlDoc(url, "service", new dojox.atom.io.model.Service(url), dojox.atom.io.model._Constants.APP_NS, callback, errorCallback, scope);
  62. },
  63. getEntry: function(url, callback, errorCallback, scope){
  64. // summary:
  65. // Function to retrieve a single entry from an ATOM feed from the given URL.
  66. // description:
  67. // This function takes the URL for an ATOM entry and returns the constructed dojox.atom.io.model.Entry object through
  68. // the specified callback.
  69. //
  70. // url:
  71. // String
  72. // The URL of the ATOM Entry document to parse.
  73. // callback:
  74. // Function
  75. // A function reference that will handle the Entry object obtained.
  76. // The callback should accept two parameters, the dojox.atom.io.model.Entry object and the original dom.
  77. //
  78. // returns:
  79. // Nothing. The return is handled through the callback handler.
  80. this._getXmlDoc(url, "entry", new dojox.atom.io.model.Entry(), dojox.atom.io.model._Constants.ATOM_NS, callback, errorCallback, scope);
  81. },
  82. _getXmlDoc: function(url, nodeName, newNode, namespace, callback, errorCallback, scope){
  83. // summary:
  84. // Internal Function to retrieve an XML document and pass the results to a callback.
  85. // description:
  86. // This internal function takes the URL for an XML document and and passes the
  87. // parsed contents to a specified callback.
  88. //
  89. // url:
  90. // String
  91. // The URL of the XML document to retrieve
  92. // callback:
  93. // Function
  94. // A function reference that will handle the retrieved XML data.
  95. // The callback should accept one parameter, the DOM of the parsed XML document.
  96. //
  97. // returns:
  98. // Nothing. The return is handled through the callback handler.
  99. if(!scope){
  100. scope = dojo.global;
  101. }
  102. var ae = this.alertsEnabled;
  103. var xhrArgs = {
  104. url: url,
  105. handleAs: "xml",
  106. sync: this.sync,
  107. preventCache: this.preventCache,
  108. load: function(data, args){
  109. var node = null;
  110. var evaldObj = data;
  111. var nodes;
  112. if(evaldObj){
  113. //find the first node of the appropriate name
  114. if(typeof(evaldObj.getElementsByTagNameNS)!= "undefined"){
  115. nodes = evaldObj.getElementsByTagNameNS(namespace,nodeName);
  116. if(nodes && nodes.length > 0){
  117. node = nodes.item(0);
  118. }else if(evaldObj.lastChild){
  119. // name_spaces can be used without declaration of atom (for example
  120. // gooogle feeds often returns iTunes name_space qualifiers on elements)
  121. // Treat this situation like name_spaces not enabled.
  122. node = evaldObj.lastChild;
  123. }
  124. }else if(typeof(evaldObj.getElementsByTagName)!= "undefined"){
  125. // Find the first eith the correct tag name and correct namespace.
  126. nodes = evaldObj.getElementsByTagName(nodeName);
  127. if(nodes && nodes.length > 0){
  128. for(var i=0; i<nodes.length; i++){
  129. if(nodes[i].namespaceURI == namespace){
  130. node = nodes[i];
  131. break;
  132. }
  133. }
  134. }else if(evaldObj.lastChild){
  135. node = evaldObj.lastChild;
  136. }
  137. }else if(evaldObj.lastChild){
  138. node = evaldObj.lastChild;
  139. }else{
  140. callback.call(scope, null, null, args);
  141. return;
  142. }
  143. newNode.buildFromDom(node);
  144. if(callback){
  145. callback.call(scope, newNode, evaldObj, args);
  146. }else if(ae){
  147. throw new Error("The callback value does not exist.");
  148. }
  149. }else{
  150. callback.call(scope, null, null, args);
  151. }
  152. }
  153. };
  154. if(this.user && this.user !== null){
  155. xhrArgs.user = this.user;
  156. }
  157. if(this.password && this.password !== null){
  158. xhrArgs.password = this.password;
  159. }
  160. if(errorCallback){
  161. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  162. }else{
  163. xhrArgs.error = function(){
  164. throw new Error("The URL requested cannot be accessed");
  165. };
  166. }
  167. dojo.xhrGet(xhrArgs);
  168. },
  169. updateEntry: function(entry, callback, errorCallback, retrieveUpdated, xmethod, scope){
  170. // summary:
  171. // Function to update a specific ATOM entry by putting the new changes via APP.
  172. // description:
  173. // This function takes a specific dojox.atom.io.model.Entry object and pushes the
  174. // changes back to the provider of the Entry.
  175. // The entry MUST have a link tag with rel="edit" for this to work.
  176. //
  177. // entry:
  178. // Object
  179. // The dojox.atom.io.model.Entry object to update.
  180. // callback:
  181. // Function
  182. // A function reference that will handle the results from the entry update.
  183. // The callback should accept two parameters: The first is an Entry object, and the second is the URL of that Entry
  184. // Either can be null, depending on the value of retrieveUpdated.
  185. // retrieveUpdated:
  186. // boolean
  187. // A boolean flag denoting if the entry that was updated should then be
  188. // retrieved and returned to the caller via the callback.
  189. // xmethod:
  190. // boolean
  191. // Whether to use POST for PUT/DELETE items and send the X-Method-Override header.
  192. // scope:
  193. // Object
  194. // The scope to use for all callbacks.
  195. //
  196. // returns:
  197. // Nothing. The return is handled through the callback handler.
  198. if(!scope){
  199. scope = dojo.global;
  200. }
  201. entry.updated = new Date();
  202. var url = entry.getEditHref();
  203. if(!url){
  204. throw new Error("A URL has not been specified for editing this entry.");
  205. }
  206. var self = this;
  207. var ae = this.alertsEnabled;
  208. var xhrArgs = {
  209. url: url,
  210. handleAs: "text",
  211. contentType: "text/xml",
  212. sync: this.sync,
  213. preventCache: this.preventCache,
  214. load: function(data, args){
  215. var location = null;
  216. if(retrieveUpdated){
  217. location = args.xhr.getResponseHeader("Location");
  218. if(!location){location = url;}
  219. //Function to handle the callback mapping of a getEntry after an update to return the
  220. //entry and location.
  221. var handleRetrieve = function(entry, dom, args){
  222. if(callback){
  223. callback.call(scope, entry, location, args);
  224. }else if(ae){
  225. throw new Error("The callback value does not exist.");
  226. }
  227. };
  228. self.getEntry(location,handleRetrieve);
  229. }else{
  230. if(callback){
  231. callback.call(scope, entry, args.xhr.getResponseHeader("Location"), args);
  232. }else if(ae){
  233. throw new Error("The callback value does not exist.");
  234. }
  235. }
  236. return data;
  237. }
  238. };
  239. if(this.user && this.user !== null){
  240. xhrArgs.user = this.user;
  241. }
  242. if(this.password && this.password !== null){
  243. xhrArgs.password = this.password;
  244. }
  245. if(errorCallback){
  246. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  247. }else{
  248. xhrArgs.error = function(){
  249. throw new Error("The URL requested cannot be accessed");
  250. };
  251. }
  252. if(xmethod){
  253. xhrArgs.postData = entry.toString(true); //Set the content to send.
  254. xhrArgs.headers = {"X-Method-Override": "PUT"};
  255. dojo.rawXhrPost(xhrArgs);
  256. }else{
  257. xhrArgs.putData = entry.toString(true); //Set the content to send.
  258. var xhr = dojo.rawXhrPut(xhrArgs);
  259. }
  260. },
  261. addEntry: function(entry, url, callback, errorCallback, retrieveEntry, scope){
  262. // summary:
  263. // Function to add a new ATOM entry by posting the new entry via APP.
  264. // description:
  265. // This function takes a specific dojox.atom.io.model.Entry object and pushes the
  266. // changes back to the provider of the Entry.
  267. //
  268. // entry:
  269. // Object
  270. // The dojox.atom.io.model.Entry object to publish.
  271. // callback:
  272. // Function
  273. // A function reference that will handle the results from the entry publish.
  274. // The callback should accept two parameters: The first is an dojox.atom.io.model.Entry object, and the second is the location of the entry
  275. // Either can be null, depending on the value of retrieveUpdated.
  276. // retrieveEntry:
  277. // boolean
  278. // A boolean flag denoting if the entry that was created should then be
  279. // retrieved and returned to the caller via the callback.
  280. // scope:
  281. // Object
  282. // The scope to use for all callbacks.
  283. //
  284. // returns:
  285. // Nothing. The return is handled through the callback handler.
  286. if(!scope){
  287. scope = dojo.global;
  288. }
  289. entry.published = new Date();
  290. entry.updated = new Date();
  291. var feedUrl = entry.feedUrl;
  292. var ae = this.alertsEnabled;
  293. //Determine which URL to use for the post.
  294. if(!url && feedUrl){url = feedUrl;}
  295. if(!url){
  296. if(ae){
  297. throw new Error("The request cannot be processed because the URL parameter is missing.");
  298. }
  299. return;
  300. }
  301. var self = this;
  302. var xhrArgs = {
  303. url: url,
  304. handleAs: "text",
  305. contentType: "text/xml",
  306. sync: this.sync,
  307. preventCache: this.preventCache,
  308. postData: entry.toString(true),
  309. load: function(data, args){
  310. var location = args.xhr.getResponseHeader("Location");
  311. if(!location){
  312. location = url;
  313. }
  314. if(!args.retrieveEntry){
  315. if(callback){
  316. callback.call(scope, entry, location, args);
  317. }else if(ae){
  318. throw new Error("The callback value does not exist.");
  319. }
  320. }else{
  321. //Function to handle the callback mapping of a getEntry after an update to return the
  322. //entry and location.
  323. var handleRetrieve = function(entry, dom, args){
  324. if(callback){
  325. callback.call(scope, entry, location, args);
  326. }else if(ae){
  327. throw new Error("The callback value does not exist.");
  328. }
  329. };
  330. self.getEntry(location,handleRetrieve);
  331. }
  332. return data;
  333. }
  334. };
  335. if(this.user && this.user !== null){
  336. xhrArgs.user = this.user;
  337. }
  338. if(this.password && this.password !== null){
  339. xhrArgs.password = this.password;
  340. }
  341. if(errorCallback){
  342. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  343. }else{
  344. xhrArgs.error = function(){
  345. throw new Error("The URL requested cannot be accessed");
  346. };
  347. }
  348. dojo.rawXhrPost(xhrArgs);
  349. },
  350. deleteEntry: function(entry,callback,errorCallback,xmethod,scope){
  351. // summary:
  352. // Function to delete a specific ATOM entry via APP.
  353. // description:
  354. // This function takes a specific dojox.atom.io.model.Entry object and calls for a delete on the
  355. // service housing the ATOM Entry database.
  356. // The entry MUST have a link tag with rel="edit" for this to work.
  357. //
  358. // entry:
  359. // Object
  360. // The dojox.atom.io.model.Entry object to delete.
  361. // callback:
  362. // Function
  363. // A function reference that will handle the results from the entry delete.
  364. // The callback is called only if the delete is successful.
  365. //
  366. // returns:
  367. // Nothing. The return is handled through the callback handler.
  368. if(!scope){
  369. scope = dojo.global;
  370. }
  371. var url = null;
  372. if(typeof(entry) == "string"){
  373. url = entry;
  374. }else{
  375. url = entry.getEditHref();
  376. }
  377. if(!url){
  378. callback.call(scope, false, null);
  379. throw new Error("The request cannot be processed because the URL parameter is missing.");
  380. }
  381. var xhrArgs = {
  382. url: url,
  383. handleAs: "text",
  384. sync: this.sync,
  385. preventCache: this.preventCache,
  386. load: function(data, args){
  387. callback.call(scope, args);
  388. return data;
  389. }
  390. };
  391. if(this.user && this.user !== null){
  392. xhrArgs.user = this.user;
  393. }
  394. if(this.password && this.password !== null){
  395. xhrArgs.password = this.password;
  396. }
  397. if(errorCallback){
  398. xhrArgs.error = function(error, args){errorCallback.call(scope, error, args);};
  399. }else{
  400. xhrArgs.error = function(){
  401. throw new Error("The URL requested cannot be accessed");
  402. };
  403. }
  404. if(xmethod){
  405. xhrArgs.headers = {"X-Method-Override": "DELETE"};
  406. dojo.xhrPost(xhrArgs);
  407. }else{
  408. dojo.xhrDelete(xhrArgs);
  409. }
  410. }
  411. });
  412. }