123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- define("dojox/rpc/Service", ["dojo", "dojox", "dojo/AdapterRegistry", "dojo/_base/url"], function(dojo, dojox) {
- dojo.declare("dojox.rpc.Service", null, {
- constructor: function(smd, options){
- // summary:
- // Take a string as a url to retrieve an smd or an object that is an smd or partial smd to use
- // as a definition for the service
- //
- // smd: object
- // Takes a number of properties as kwArgs for defining the service. It also
- // accepts a string. When passed a string, it is treated as a url from
- // which it should synchronously retrieve an smd file. Otherwise it is a kwArgs
- // object. It accepts serviceUrl, to manually define a url for the rpc service
- // allowing the rpc system to be used without an smd definition. strictArgChecks
- // forces the system to verify that the # of arguments provided in a call
- // matches those defined in the smd. smdString allows a developer to pass
- // a jsonString directly, which will be converted into an object or alternatively
- // smdObject is accepts an smdObject directly.
- //
- // description:
- // dojox.rpc.Service must be loaded prior to any plugin services like dojox.rpc.Rest
- // dojox.rpc.JsonRpc in order for them to register themselves, otherwise you get
- // a "No match found" error.
- var url;
- var self = this;
- function processSmd(smd){
- smd._baseUrl = new dojo._Url((dojo.isBrowser ? location.href : dojo.config.baseUrl) ,url || '.') + '';
- self._smd = smd;
- //generate the methods
- for(var serviceName in self._smd.services){
- var pieces = serviceName.split("."); // handle "namespaced" services by breaking apart by .
- var current = self;
- for(var i=0; i< pieces.length-1; i++){
- // create or reuse each object as we go down the chain
- current = current[pieces[i]] || (current[pieces[i]] = {});
- }
- current[pieces[pieces.length-1]]= self._generateService(serviceName, self._smd.services[serviceName]);
- }
- }
- if(smd){
- //ifthe arg is a string, we assume it is a url to retrieve an smd definition from
- if( (dojo.isString(smd)) || (smd instanceof dojo._Url)){
- if(smd instanceof dojo._Url){
- url = smd + "";
- }else{
- url = smd;
- }
- var text = dojo._getText(url);
- if(!text){
- throw new Error("Unable to load SMD from " + smd);
- }else{
- processSmd(dojo.fromJson(text));
- }
- }else{
- processSmd(smd);
- }
- }
- this._options = (options ? options : {});
- this._requestId = 0;
- },
- _generateService: function(serviceName, method){
- if(this[method]){
- throw new Error("WARNING: "+ serviceName+ " already exists for service. Unable to generate function");
- }
- method.name = serviceName;
- var func = dojo.hitch(this, "_executeMethod",method);
- var transport = dojox.rpc.transportRegistry.match(method.transport || this._smd.transport);
- if(transport.getExecutor){
- func = transport.getExecutor(func,method,this);
- }
- var schema = method.returns || (method._schema = {}); // define the schema
- var servicePath = '/' + serviceName +'/';
- // schemas are minimally used to track the id prefixes for the different services
- schema._service = func;
- func.servicePath = servicePath;
- func._schema = schema;
- func.id = dojox.rpc.Service._nextId++;
- return func;
- },
- _getRequest: function(method,args){
- var smd = this._smd;
- var envDef = dojox.rpc.envelopeRegistry.match(method.envelope || smd.envelope || "NONE");
- var parameters = (method.parameters || []).concat(smd.parameters || []);
- if(envDef.namedParams){
- // the serializer is expecting named params
- if((args.length==1) && dojo.isObject(args[0])){
- // looks like we have what we want
- args = args[0];
- }else{
- // they provided ordered, must convert
- var data={};
- for(var i=0;i<method.parameters.length;i++){
- if(typeof args[i] != "undefined" || !method.parameters[i].optional){
- data[method.parameters[i].name]=args[i];
- }
- }
- args = data;
- }
- if(method.strictParameters||smd.strictParameters){
- //remove any properties that were not defined
- for(i in args){
- var found=false;
- for(var j=0; j<parameters.length;j++){
- if(parameters[i].name==i){ found=true; }
- }
- if(!found){
- delete args[i];
- }
- }
- }
- // setting default values
- for(i=0; i< parameters.length; i++){
- var param = parameters[i];
- if(!param.optional && param.name && !args[param.name]){
- if(param["default"]){
- args[param.name] = param["default"];
- }else if(!(param.name in args)){
- throw new Error("Required parameter " + param.name + " was omitted");
- }
- }
- }
- }else if(parameters && parameters[0] && parameters[0].name && (args.length==1) && dojo.isObject(args[0])){
- // looks like named params, we will convert
- if(envDef.namedParams === false){
- // the serializer is expecting ordered params, must be ordered
- args = dojox.rpc.toOrdered(parameters, args);
- }else{
- // named is ok
- args = args[0];
- }
- }
- if(dojo.isObject(this._options)){
- args = dojo.mixin(args, this._options);
- }
- var schema = method._schema || method.returns; // serialize with the right schema for the context;
- var request = envDef.serialize.apply(this, [smd, method, args]);
- request._envDef = envDef;// save this for executeMethod
- var contentType = (method.contentType || smd.contentType || request.contentType);
- // this allows to mandate synchronous behavior from elsewhere when necessary, this may need to be changed to be one-shot in FF3 new sync handling model
- return dojo.mixin(request, {
- sync: dojox.rpc._sync,
- contentType: contentType,
- headers: method.headers || smd.headers || request.headers || {},
- target: request.target || dojox.rpc.getTarget(smd, method),
- transport: method.transport || smd.transport || request.transport,
- envelope: method.envelope || smd.envelope || request.envelope,
- timeout: method.timeout || smd.timeout,
- callbackParamName: method.callbackParamName || smd.callbackParamName,
- rpcObjectParamName: method.rpcObjectParamName || smd.rpcObjectParamName,
- schema: schema,
- handleAs: request.handleAs || "auto",
- preventCache: method.preventCache || smd.preventCache,
- frameDoc: this._options.frameDoc || undefined
- });
- },
- _executeMethod: function(method){
- var args = [];
- var i;
- for(i=1; i< arguments.length; i++){
- args.push(arguments[i]);
- }
- var request = this._getRequest(method,args);
- var deferred = dojox.rpc.transportRegistry.match(request.transport).fire(request);
- deferred.addBoth(function(results){
- return request._envDef.deserialize.call(this,results);
- });
- return deferred;
- }
- });
- dojox.rpc.getTarget = function(smd, method){
- var dest=smd._baseUrl;
- if(smd.target){
- dest = new dojo._Url(dest,smd.target) + '';
- }
- if(method.target){
- dest = new dojo._Url(dest,method.target) + '';
- }
- return dest;
- };
- dojox.rpc.toOrdered=function(parameters, args){
- if(dojo.isArray(args)){ return args; }
- var data=[];
- for(var i=0;i<parameters.length;i++){
- data.push(args[parameters[i].name]);
- }
- return data;
- };
- dojox.rpc.transportRegistry = new dojo.AdapterRegistry(true);
- dojox.rpc.envelopeRegistry = new dojo.AdapterRegistry(true);
- //Built In Envelopes
- dojox.rpc.envelopeRegistry.register(
- "URL",
- function(str){ return str == "URL"; },
- {
- serialize:function(smd, method, data ){
- var d = dojo.objectToQuery(data);
- return {
- data: d,
- transport:"POST"
- };
- },
- deserialize:function(results){
- return results;
- },
- namedParams: true
- }
- );
- dojox.rpc.envelopeRegistry.register(
- "JSON",
- function(str){ return str == "JSON"; },
- {
- serialize: function(smd, method, data){
- var d = dojo.toJson(data);
- return {
- data: d,
- handleAs: 'json',
- contentType : 'application/json'
- };
- },
- deserialize: function(results){
- return results;
- }
- }
- );
- dojox.rpc.envelopeRegistry.register(
- "PATH",
- function(str){ return str == "PATH"; },
- {
- serialize:function(smd, method, data){
- var i;
- var target = dojox.rpc.getTarget(smd, method);
- if(dojo.isArray(data)){
- for(i = 0; i < data.length;i++){
- target += '/' + data[i];
- }
- }else{
- for(i in data){
- target += '/' + i + '/' + data[i];
- }
- }
- return {
- data:'',
- target: target
- };
- },
- deserialize:function(results){
- return results;
- }
- }
- );
- //post is registered first because it is the default;
- dojox.rpc.transportRegistry.register(
- "POST",
- function(str){ return str == "POST"; },
- {
- fire:function(r){
- r.url = r.target;
- r.postData = r.data;
- return dojo.rawXhrPost(r);
- }
- }
- );
- dojox.rpc.transportRegistry.register(
- "GET",
- function(str){ return str == "GET"; },
- {
- fire: function(r){
- r.url= r.target + (r.data ? '?' + ((r.rpcObjectParamName) ? r.rpcObjectParamName + '=' : '') + r.data : '');
- return dojo.xhrGet(r);
- }
- }
- );
- //only works ifyou include dojo.io.script
- dojox.rpc.transportRegistry.register(
- "JSONP",
- function(str){ return str == "JSONP"; },
- {
- fire: function(r){
- r.url = r.target + ((r.target.indexOf("?") == -1) ? '?' : '&') + ((r.rpcObjectParamName) ? r.rpcObjectParamName + '=' : '') + r.data;
- r.callbackParamName = r.callbackParamName || "callback";
- return dojo.io.script.get(r);
- }
- }
- );
- dojox.rpc.Service._nextId = 1;
- dojo._contentHandlers.auto = function(xhr){
- // automatically choose the right handler based on the returned content type
- var handlers = dojo._contentHandlers;
- var retContentType = xhr.getResponseHeader("Content-Type");
- var results = !retContentType ? handlers.text(xhr) :
- retContentType.match(/\/.*json/) ? handlers.json(xhr) :
- retContentType.match(/\/javascript/) ? handlers.javascript(xhr) :
- retContentType.match(/\/xml/) ? handlers.xml(xhr) : handlers.text(xhr);
- return results;
- };
- return dojox.rpc.Service;
- });
|