Service.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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.wire.ml.Service"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.wire.ml.Service"] = true;
  8. dojo.provide("dojox.wire.ml.Service");
  9. dojo.provide("dojox.wire.ml.RestHandler");
  10. dojo.provide("dojox.wire.ml.XmlHandler");
  11. dojo.provide("dojox.wire.ml.JsonHandler");
  12. dojo.require("dijit._Widget");
  13. dojo.require("dojox.xml.parser");
  14. dojo.require("dojox.wire._base");
  15. dojo.require("dojox.wire.ml.util");
  16. dojo.declare("dojox.wire.ml.Service", dijit._Widget, {
  17. // summary:
  18. // A widget for a service
  19. // description:
  20. // This widget represents a service defined by a service description
  21. // specified with 'url' attribute.
  22. // If 'serviceType' and 'serviceUrl' attributes are specified, 'url'
  23. // attribute can be omitted.
  24. // url:
  25. // A URL to a service description
  26. // serviceUrl:
  27. // A URL to a service
  28. // serviceType:
  29. // A service type
  30. // handlerClass:
  31. // A service handler class name
  32. url: "",
  33. serviceUrl: "",
  34. serviceType: "",
  35. handlerClass: "",
  36. preventCache: true,
  37. postCreate: function(){
  38. // summary:
  39. // Call _createHandler()
  40. // description:
  41. // See _createHandler().
  42. this.handler = this._createHandler();
  43. },
  44. _handlerClasses: {
  45. "TEXT": "dojox.wire.ml.RestHandler",
  46. "XML": "dojox.wire.ml.XmlHandler",
  47. "JSON": "dojox.wire.ml.JsonHandler",
  48. "JSON-RPC": "dojo.rpc.JsonService"
  49. },
  50. _createHandler: function(){
  51. // summary:
  52. // Create a service handler
  53. // desription:
  54. // A service handler class is determined by:
  55. // 1. 'handlerClass' attribute
  56. // 2. 'serviceType' attribute
  57. // 3. 'serviceType' property in a service description
  58. // returns:
  59. // A service handler
  60. if(this.url){
  61. var self = this;
  62. var d = dojo.xhrGet({
  63. url: this.url,
  64. handleAs: "json",
  65. sync: true
  66. });
  67. d.addCallback(function(result){
  68. self.smd = result;
  69. });
  70. if(this.smd && !this.serviceUrl){
  71. this.serviceUrl = (this.smd.serviceUrl || this.smd.serviceURL);
  72. }
  73. }
  74. var handlerClass = undefined;
  75. if(this.handlerClass){
  76. handlerClass = dojox.wire._getClass(this.handlerClass);
  77. }else if(this.serviceType){
  78. handlerClass = this._handlerClasses[this.serviceType];
  79. if(handlerClass && dojo.isString(handlerClass)){
  80. handlerClass = dojox.wire._getClass(handlerClass);
  81. this._handlerClasses[this.serviceType] = handlerClass;
  82. }
  83. }else if(this.smd && this.smd.serviceType){
  84. handlerClass = this._handlerClasses[this.smd.serviceType];
  85. if(handlerClass && dojo.isString(handlerClass)){
  86. handlerClass = dojox.wire._getClass(handlerClass);
  87. this._handlerClasses[this.smd.serviceType] = handlerClass;
  88. }
  89. }
  90. if(!handlerClass){
  91. return null; //null
  92. }
  93. return new handlerClass(); //Object
  94. },
  95. callMethod: function(method, parameters){
  96. // summary:
  97. // Call a service method with parameters
  98. // method:
  99. // A method name
  100. // parameters:
  101. // An array parameters
  102. var deferred = new dojo.Deferred();
  103. this.handler.bind(method, parameters, deferred, this.serviceUrl);
  104. return deferred;
  105. }
  106. });
  107. dojo.declare("dojox.wire.ml.RestHandler", null, {
  108. // summary:
  109. // A REST service handler
  110. // description:
  111. // This class serves as a base REST service.
  112. // Sub-classes may override _getContent() and _getResult() to handle
  113. // specific content types.
  114. contentType: "text/plain",
  115. handleAs: "text",
  116. bind: function(method, parameters, deferred, url){
  117. // summary:
  118. // Call a service method with parameters.
  119. // description:
  120. // A service is called with a URL generated by _getUrl() and
  121. // an HTTP method specified with 'method'.
  122. // For "POST" and "PUT", a content is generated by _getContent().
  123. // When data is loaded, _getResult() is used to pass the result to
  124. // Deferred.callback().
  125. // method:
  126. // A method name
  127. // parameters:
  128. // An array of parameters
  129. // deferred:
  130. // 'Deferred'
  131. // url:
  132. // A URL for the method
  133. method = method.toUpperCase();
  134. var self = this;
  135. var args = {
  136. url: this._getUrl(method, parameters, url),
  137. contentType: this.contentType,
  138. handleAs: this.handleAs,
  139. headers: this.headers,
  140. preventCache: this.preventCache
  141. };
  142. var d = null;
  143. if(method == "POST"){
  144. args.postData = this._getContent(method, parameters);
  145. d = dojo.rawXhrPost(args);
  146. }else if(method == "PUT"){
  147. args.putData = this._getContent(method, parameters);
  148. d = dojo.rawXhrPut(args);
  149. }else if(method == "DELETE"){
  150. d = dojo.xhrDelete(args);
  151. }else{ // "GET"
  152. d = dojo.xhrGet(args);
  153. }
  154. d.addCallbacks(function(result){
  155. deferred.callback(self._getResult(result));
  156. }, function(error){
  157. deferred.errback(error);
  158. });
  159. },
  160. _getUrl: function(/*String*/method, /*Array*/parameters, /*String*/url){
  161. // summary:
  162. // Generate a URL
  163. // description:
  164. // If 'method' is "GET" or "DELETE", a query string is generated
  165. // from a query object specified to the first parameter in
  166. // 'parameters' and appended to 'url'.
  167. // If 'url' contains variable seguments ("{parameter_name}"),
  168. // they are replaced with corresponding parameter values, instead.
  169. // method:
  170. // A method name
  171. // parameters:
  172. // An array of parameters
  173. // url:
  174. // A base URL
  175. // returns:
  176. // A URL
  177. var query;
  178. if(method == "GET" || method == "DELETE"){
  179. if(parameters.length > 0){
  180. query = parameters[0];
  181. }
  182. }else{ // "POST" || "PUT"
  183. if(parameters.length > 1){
  184. query = parameters[1];
  185. }
  186. }
  187. if(query){
  188. var queryString = "";
  189. for(var name in query){
  190. var value = query[name];
  191. if(value){
  192. value = encodeURIComponent(value);
  193. var variable = "{" + name + "}";
  194. var index = url.indexOf(variable);
  195. if(index >= 0){ // encode in path
  196. url = url.substring(0, index) + value + url.substring(index + variable.length);
  197. }else{ // encode as query string
  198. if(queryString){
  199. queryString += "&";
  200. }
  201. queryString += (name + "=" + value);
  202. }
  203. }
  204. }
  205. if(queryString){
  206. url += "?" + queryString;
  207. }
  208. }
  209. return url; //String
  210. },
  211. _getContent: function(/*String*/method, /*Array*/parameters){
  212. // summary:
  213. // Generate a request content
  214. // description:
  215. // If 'method' is "POST" or "PUT", the first parameter in
  216. // 'parameters' is returned.
  217. // method:
  218. // A method name
  219. // parameters:
  220. // An array of parameters
  221. // returns:
  222. // A request content
  223. if(method == "POST" || method == "PUT"){
  224. return (parameters ? parameters[0] : null); //anything
  225. }else{
  226. return null; //null
  227. }
  228. },
  229. _getResult: function(/*anything*/data){
  230. // summary:
  231. // Extract a result
  232. // description:
  233. // A response data is returned as is.
  234. // data:
  235. // A response data returned by a service
  236. // returns:
  237. // A result object
  238. return data; //anything
  239. }
  240. });
  241. dojo.declare("dojox.wire.ml.XmlHandler", dojox.wire.ml.RestHandler, {
  242. // summary:
  243. // A REST service handler for XML
  244. // description:
  245. // This class provides XML handling for a REST service.
  246. contentType: "text/xml",
  247. handleAs: "xml",
  248. _getContent: function(/*String*/method, /*Array*/parameters){
  249. // description:
  250. // If 'method' is "POST" or "PUT", the first parameter in
  251. // 'parameters' is used to generate an XML content.
  252. // method:
  253. // A method name
  254. // parameters:
  255. // An array of parameters
  256. // returns:
  257. // A request content
  258. var content = null;
  259. if(method == "POST" || method == "PUT"){
  260. var p = parameters[0];
  261. if(p){
  262. if(dojo.isString(p)){
  263. content = p;
  264. }else{
  265. var element = p;
  266. if(element instanceof dojox.wire.ml.XmlElement){
  267. element = element.element;
  268. }else if(element.nodeType === 9 /* DOCUMENT_NODE */){
  269. element = element.documentElement;
  270. }
  271. var declaration = "<?xml version=\"1.0\"?>"; // TODO: encoding?
  272. content = declaration + dojox.xml.parser.innerXML(element);
  273. }
  274. }
  275. }
  276. return content;
  277. },
  278. _getResult: function(/*Document*/data){
  279. // summary:
  280. // Extract a result
  281. // description:
  282. // A response data (XML Document) is returned wrapped with
  283. // XmlElement.
  284. // data:
  285. // A response data returned by a service
  286. // returns:
  287. // A result object
  288. if(data){
  289. data = new dojox.wire.ml.XmlElement(data);
  290. }
  291. return data;
  292. }
  293. });
  294. dojo.declare("dojox.wire.ml.JsonHandler", dojox.wire.ml.RestHandler, {
  295. // summary:
  296. // A REST service handler for JSON
  297. // description:
  298. // This class provides JSON handling for a REST service.
  299. contentType: "text/json",
  300. handleAs: "json",
  301. headers: {"Accept": "*/json"},
  302. _getContent: function(/*String*/method, /*Array*/parameters){
  303. // summary:
  304. // Generate a request content
  305. // description:
  306. // If 'method' is "POST" or "PUT", the first parameter in
  307. // 'parameter' is used to generate a JSON content.
  308. // method:
  309. // A method name
  310. // parameters:
  311. // An array of parameters
  312. // returns:
  313. // A request content
  314. var content = null;
  315. if(method == "POST" || method == "PUT"){
  316. var p = (parameters ? parameters[0] : undefined);
  317. if(p){
  318. if(dojo.isString(p)){
  319. content = p;
  320. }else{
  321. content = dojo.toJson(p);
  322. }
  323. }
  324. }
  325. return content; //String
  326. }
  327. });
  328. }