Exemple #1
0
        public virtual ServiceClass GetClass()
        {
            if (_class == null)
                _class = JsonRpcServices.GetClassFromType(GetType());

            return _class;
        }
        public static void Generate(ServiceClass service, Uri url, TextWriter writer)
        {
            if (service == null) throw new ArgumentNullException("service");
            if (url == null) throw new ArgumentNullException("url");
            if (writer == null) throw new ArgumentNullException("writer");

            Version1(service, url, new IndentedTextWriter(writer));
        }
        private void WriteClass(IndentedTextWriter writer, ServiceClass serviceClass)
        {
            writer.Write("class ");
            writer.Write(serviceClass.Name);
            writer.WriteLine(":");
            writer.Indent++;

            writer.Write(_docQuotes);
            writer.Indent--;

            if (serviceClass.Description.Length > 0)
            {
                writer.WriteLine(serviceClass.Description);
                writer.WriteLine();
            }

            writer.WriteLine("This Python class was automatically generated by");
            writer.WriteLine(GetType().AssemblyQualifiedName);

            DateTime now = DateTime.Now;
            writer.Write("on ");
            writer.Write(now.ToLongDateString());
            writer.Write(" at ");
            writer.Write(now.ToLongTimeString());

            writer.Write(" (");
            TimeZone timeZone = TimeZone.CurrentTimeZone;
            writer.Write(timeZone.IsDaylightSavingTime(now) ?
                         timeZone.DaylightName : timeZone.StandardName);
            writer.WriteLine(")");

            writer.WriteLine(_docQuotes);
            writer.Indent++;

            Uri url = new Uri(Request.Url.GetLeftPart(UriPartial.Path));
            writer.WriteLine(@"def __init__(self, url = '" + url + @"'):
            self.url = url
            self.__id = 0");

            writer.WriteLine();
        }
Exemple #4
0
        internal Method(MethodBuilder methodBuilder, ServiceClass clazz)
        {
            Debug.Assert(methodBuilder != null);
            Debug.Assert(clazz != null);

            _name         = methodBuilder.Name;
            _internalName = Mask.EmptyString(methodBuilder.InternalName, methodBuilder.Name);
            _resultType   = methodBuilder.ResultType;
            _description  = methodBuilder.Description;
            _handler      = methodBuilder.Handler;
            _idempotent   = methodBuilder.Idempotent;
            _attributes   = methodBuilder.CustomAttributes;
            _class        = clazz;

            //
            // Set up parameters and their names.
            //

            ICollection parameterBuilders = methodBuilder.Parameters;

            _parameters     = new Parameter[parameterBuilders.Count];
            _parameterNames = new string[parameterBuilders.Count];

            foreach (ParameterBuilder parameterBuilder in parameterBuilders)
            {
                Parameter parameter = new Parameter(parameterBuilder, this);
                int       position  = parameter.Position;
                _parameters[position]     = parameter;
                _parameterNames[position] = parameter.Name;
            }

            //
            // Keep a sorted list of parameters and their names so we can
            // do fast look ups using binary search.
            //

            _sortedParameters = (Parameter[])_parameters.Clone();
            InvariantStringArray.Sort(_parameterNames, _sortedParameters);
        }
        internal Method(MethodBuilder methodBuilder, ServiceClass clazz)
        {
            Debug.Assert(methodBuilder != null);
            Debug.Assert(clazz != null);
            
            _name = methodBuilder.Name;
            _internalName = Mask.EmptyString(methodBuilder.InternalName, methodBuilder.Name);
            _resultType = methodBuilder.ResultType;
            _description = methodBuilder.Description;
            _handler = methodBuilder.Handler;
            _idempotent = methodBuilder.Idempotent;
            _attributes = DeepCopy(methodBuilder.GetCustomAttributes());
            _class = clazz;
            
            //
            // Set up parameters and their names.
            //
            
            ICollection parameterBuilders = methodBuilder.Parameters;
            _parameters = new Parameter[parameterBuilders.Count];
            _parameterNames = new string[parameterBuilders.Count];

            foreach (ParameterBuilder parameterBuilder in parameterBuilders)
            {
                Parameter parameter = new Parameter(parameterBuilder, this);
                int position = parameter.Position;
                _parameters[position] = parameter;
                _parameterNames[position] = parameter.Name;
            }
            
            //
            // Keep a sorted list of parameters and their names so we can
            // do fast look ups using binary search.
            //
            
            _sortedParameters = (Parameter[]) _parameters.Clone();
            InvariantStringArray.Sort(_parameterNames, _sortedParameters);
        }
        private static void Version1(ServiceClass service, Uri url, IndentedTextWriter writer)
        {
            Debug.Assert(service != null);
            Debug.Assert(url!= null);
            Debug.Assert(!url.IsFile);
            Debug.Assert(writer != null);

            writer.Write("function ");
            writer.Write(service.Name);
            writer.WriteLine("(url)");
            writer.WriteLine("{");
            writer.Indent++;
            writer.WriteLine("var self = this;");
            
            Method[] methods = service.GetMethods();
            
            string[] methodNames = new string[methods.Length];
            bool[] idempotents = new bool[methods.Length];

            for (int i = 0; i < methods.Length; i++)
            {
                methodNames[i] = methods[i].Name;
                idempotents[i] = methods[i].Idempotent;
            }

            writer.Write("var m = ");
            JsonConvert.Export(methodNames, writer);
            writer.WriteLine(';');
            writer.Write("var idems = ");
            JsonConvert.Export(idempotents, writer);
            writer.WriteLine(';');
            writer.WriteLine();
    
            for (int i = 0; i < methods.Length; i++)
            {
                Method method = methods[i];
                string index = i.ToString(CultureInfo.InvariantCulture);

                if (method.Description.Length > 0)
                {
                    // TODO: What to do if summary breaks over several lines?

                    writer.Write("// ");
                    writer.WriteLine(method.Description);
                    writer.WriteLine();
                }

                writer.Write("this[m[");
                writer.Write(index);
                writer.Write("]] = function /* "); 
                writer.Write(method.Name);
                writer.Write(" */ (");

                Parameter[] parameters = method.GetParameters();
                
                foreach (Parameter parameter in parameters)
                {
                    writer.Write(parameter.Name);
                    writer.Write(", ");
                }

                writer.WriteLine("callback)");
                writer.WriteLine("{");
                writer.Indent++;

                writer.Write("if (self.kwargs) return rpc(new Call(");
                writer.Write(index);
                writer.Write(", {");

                foreach (Parameter parameter in parameters)
                {
                    if (parameter.Position > 0)
                        writer.Write(',');
                    writer.Write(' ');
                    writer.Write(parameter.Name);
                    writer.Write(": ");
                    writer.Write(parameter.Name);
                }

                writer.WriteLine(" }, callback));");

                writer.Write("return rpc(new Call(");
                writer.Write(index);
                writer.Write(", [");

                foreach (Parameter parameter in parameters)
                {
                    if (parameter.Position > 0)
                        writer.Write(',');
                    writer.Write(' ');
                    writer.Write(parameter.Name);
                }

                writer.WriteLine(" ], callback));");

                writer.Indent--;
                writer.WriteLine("}");
                writer.WriteLine();
            }
    
            writer.Write("var url = typeof(url) === 'string' ? url : '");
            writer.Write(url);
            writer.WriteLine("';");
            writer.WriteLine(@"var nextId = 0;

    function Call(method, params, callback)
    {
        this.url = url;
        this.callback = callback;
        this.proxy = self;
        this.idempotent = idems[method];
        this.request = 
        { 
            id     : ++nextId, 
            method : m[method], 
            params : params 
        };
    }

    function rpc(call)
    {
        return self.channel != null && typeof(self.channel.rpc) === 'function' ?
            self.channel.rpc(call) : call;
    }

    this.kwargs = false;
    this.channel = new JayrockChannel();

    function JayrockChannel()
    {
        this.rpc = function(call)
        {
            var async = typeof(call.callback) === 'function';
            var xhr = newXHR();
            xhr.open('POST', call.url, async, this.httpUserName, this.httpPassword);
            xhr.setRequestHeader('Content-Type', this.contentType || 'application/json; charset=utf-8');
            xhr.setRequestHeader('X-JSON-RPC', call.request.method);
            if (async) xhr.onreadystatechange = function() { xhr_onreadystatechange(xhr, call.callback); }
            xhr.send(JSON.stringify(call.request));
            call.handler = xhr;
            if (async) return call;
            if (xhr.status != 200) throw new Error(xhr.status + ' ' + xhr.statusText);
            var response = JSON.parse(xhr.responseText);
            if (response.error != null) throw response.error;
            return response.result;
        }

        function xhr_onreadystatechange(sender, callback)
        {
            if (sender.readyState == /* complete */ 4)
            {
                try { 
                    sender.onreadystatechange = null; // Avoid IE7 leak (bug #12964)
                } 
                catch (e) { 
                    /* IE 6/Mobile throws for onreadystatechange = null */ 
                }

                var response = sender.status == 200 ? 
                    JSON.parse(sender.responseText) : {};
                
                callback(response, sender);
            }
        }

        function newXHR()
        {
            if (typeof(window) !== 'undefined' && window.XMLHttpRequest)
                return new XMLHttpRequest(); /* IE7, Safari 1.2, Mozilla 1.0/Firefox, and Netscape 7 */
            else
                return new ActiveXObject('Microsoft.XMLHTTP'); /* WSH and IE 5 to IE 6 */
        }
    }");
    
            writer.Indent--;
            writer.WriteLine("}");
    
            writer.WriteLine();
            writer.Write(service.Name);
            writer.Write(".rpcMethods = ");
            JsonConvert.Export(methodNames, writer);
            writer.WriteLine(";");
        }
        private void Version2(ServiceClass service, Uri url, IndentedTextWriter writer)
        {
            Debug.Assert(service != null);
            Debug.Assert(url!= null);
            Debug.Assert(!url.IsFile);
            Debug.Assert(writer != null);
            
            if (JsonRpcTrace.TraceWarning)
            {
                writer.WriteLine(@"// *** O B S O L E T E *** 
//
// You are using version 2 of the JavaScript proxy that MAY 
// be obsoleted and removed in the next release. The functionality has 
// been integrated into the original proxy version via the channel 
// property on the JavaScript proxy.
");
            }
 
            writer.WriteLine("// Proxy version 2.0");
            writer.WriteLine();
 
            writer.Write("var ");
            writer.Write(service.Name);
            writer.Write(@" = function()
{
    var nextId = 0;

    var proxy = {

        url : """);
            writer.Write(url);
            writer.Write(@""",
        rpc : {");
            writer.WriteLine();
            writer.Indent += 3;
    
            Method[] methods = service.GetMethods();
            
            string[] methodNames = new string[methods.Length];
            for (int i = 0; i < methods.Length; i++)
                methodNames[i] = methods[i].Name;
            
            Array.Sort(methodNames, methods);
    
            for (int i = 0; i < methods.Length; i++)
            {
                Method method = methods[i];

                writer.WriteLine();

                if (method.Description.Length > 0)
                {
                    // TODO: What to do if /* and */ appear in the summary?

                    writer.Write("/* ");
                    writer.Write(method.Description);
                    writer.WriteLine(" */");
                    writer.WriteLine();
                }

                writer.Write('\"');
                writer.Write(method.Name);
                writer.Write("\" : function(");

                Parameter[] parameters = method.GetParameters();
                
                foreach (Parameter parameter in parameters)
                {
                    writer.Write(parameter.Name);
                    writer.Write(", ");
                }

                writer.WriteLine("callback) {");
                writer.Indent++;

                writer.Write("return new Call(\"");
                writer.Write(method.Name);
                writer.Write("\", [");

                foreach (Parameter parameter in parameters)
                {
                    if (parameter.Position > 0)
                        writer.Write(',');
                    writer.Write(' ');
                    writer.Write(parameter.Name);
                }

                writer.WriteLine(" ], callback);");

                writer.Indent--;
                writer.Write("}");
                if (i < (methods.Length - 1))
                    writer.Write(',');
                writer.WriteLine();
            }
    
            writer.Indent--;
            writer.WriteLine(@"}
    }

    function Call(method, params, callback)
    {
        this.url = proxy.url;
        this.callback = callback;
        this.request = 
        { 
            id     : ++nextId, 
            method : method, 
            params : params
        };
    }
    
    Call.prototype.call = function(channel) { return channel(this); }
    
    return proxy;
}();");
    
            writer.Indent--;
        }
        private void WriteClassTail(IndentedTextWriter writer, ServiceClass serviceClass)
        {
            writer.WriteLine(@"def __call(self, method, params):
            self.__id = self.__id + 1
            response = simplejson.loads(urllib.urlopen(self.url, urllib.urlencode([('JSON-RPC', simplejson.dumps({ 'id' : self.__id, 'method' : method, 'params' : params }))])).read())
            if response.has_key('error'): raise Error(None, response)
            return response['result']
            ");

            writer.Indent--;
        }
        private static void Version1(ServiceClass service, Uri url, IndentedTextWriter writer)
        {
            Debug.Assert(service != null);
            Debug.Assert(url!= null);
            Debug.Assert(!url.IsFile);
            Debug.Assert(writer != null);

            writer.WriteLine("// Proxy version 1.0");
            writer.WriteLine();

            writer.Write("function ");
            writer.Write(service.Name);
            writer.WriteLine("(url)");
            writer.WriteLine("{");
            writer.Indent++;

            Method[] methods = service.GetMethods();
            string[] methodNames = new string[methods.Length];

            for (int i = 0; i < methods.Length; i++)
            {
                Method method = methods[i];
                methodNames[i] = method.Name;

                if (method.Description.Length > 0)
                {
                    // TODO: What to do if /* and */ appear in the summary?

                    writer.Write("/* ");
                    writer.Write(method.Description);
                    writer.WriteLine(" */");
                    writer.WriteLine();
                }

                writer.Write("this[\"");
                writer.Write(method.Name);
                writer.Write("\"] = function(");

                Parameter[] parameters = method.GetParameters();

                foreach (Parameter parameter in parameters)
                {
                    writer.Write(parameter.Name);
                    writer.Write(", ");
                }

                writer.WriteLine("callback)");
                writer.WriteLine("{");
                writer.Indent++;

                writer.Write("return call(\"");
                writer.Write(method.Name);
                writer.Write("\", [");

                foreach (Parameter parameter in parameters)
                {
                    if (parameter.Position > 0)
                        writer.Write(',');
                    writer.Write(' ');
                    writer.Write(parameter.Name);
                }

                writer.WriteLine(" ], callback);");

                writer.Indent--;
                writer.WriteLine("}");
                writer.WriteLine();
            }

            writer.Write("var url = typeof(url) === 'string' ? url : '");
            writer.Write(url);
            writer.WriteLine("';");
            writer.WriteLine(@"var self = this;
            var nextId = 0;

            function call(method, params, callback)
            {
            var request = { id : nextId++, method : method, params : params };
            return callback == null ?
            callSync(method, request) : callAsync(method, request, callback);
            }

            function callSync(method, request)
            {
            var http = newHTTP();
            http.open('POST', url, false, self.httpUserName, self.httpPassword);
            setupHeaders(http, method);
            http.send(JSON.stringify(request));
            if (http.status != 200)
            throw { message : http.status + ' ' + http.statusText, toString : function() { return message; } };
            var response = JSON.eval(http.responseText);
            if (response.error != null) throw response.error;
            return response.result;
            }

            function callAsync(method, request, callback)
            {
            var http = newHTTP();
            http.open('POST', url, true, self.httpUserName, self.httpPassword);
            setupHeaders(http, method);
            http.onreadystatechange = function() { http_onreadystatechange(http, callback); }
            http.send(JSON.stringify(request));
            return request.id;
            }

            function setupHeaders(http, method)
            {
            http.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');
            http.setRequestHeader('X-JSON-RPC', method);
            }

            function http_onreadystatechange(sender, callback)
            {
            if (sender.readyState == /* complete */ 4)
            {
            var response = sender.status == 200 ?
                JSON.eval(sender.responseText) : {};

            response.xmlHTTP = sender;

            callback(response);
            }
            }

            function newHTTP()
            {
            if (typeof(window) != 'undefined' && window.XMLHttpRequest)
            return new XMLHttpRequest(); /* IE7, Safari 1.2, Mozilla 1.0/Firefox, and Netscape 7 */
            else
            return new ActiveXObject('Microsoft.XMLHTTP'); /* WSH and IE 5 to IE 6 */
            }");

            writer.Indent--;
            writer.WriteLine("}");

            writer.WriteLine();
            writer.Write(service.Name);
            writer.Write(".rpcMethods = ");
            JsonTextWriter jsonWriter = new JsonTextWriter(writer);
            jsonWriter.WriteStringArray(methodNames);
            writer.WriteLine(";");
        }
Exemple #10
0
        public void CustomServiceName()
        {
            ServiceClass clazz = JsonRpcServices.GetClassFromType(typeof(TestService));

            Assert.AreEqual("MyService", clazz.Name);
        }
Exemple #11
0
        public void MethodLookupIsCaseInsensitive()
        {
            ServiceClass clazz = JsonRpcServices.GetClassFromType(typeof(TestService));

            Assert.IsNotNull(clazz.FindMethodByName("FOO"));
        }
Exemple #12
0
        public void TaggedMethodsExported()
        {
            ServiceClass clazz = JsonRpcServices.GetClassFromType(typeof(TestService));

            Assert.AreEqual(2, clazz.GetMethods().Length);
        }
Exemple #13
0
        public void UntaggedMethodsNotExported()
        {
            ServiceClass clazz = JsonRpcServices.GetClassFromType(typeof(EmptyService));

            Assert.AreEqual(0, clazz.GetMethods().Length);
        }
Exemple #14
0
        public void ServiceNameIsTypeName()
        {
            ServiceClass clazz = JsonRpcServices.GetClassFromType(typeof(EmptyService));

            Assert.AreEqual("EmptyService", clazz.Name);
        }
 protected abstract void WriteClassTail(IndentedTextWriter writer, ServiceClass serviceClass);
 protected override void WriteClassTail(IndentedTextWriter writer, ServiceClass serviceClass)
 {
     throw new NotImplementedException();
 }