      1 /*
      2 Script: Deluge.Client.js
      3     A JSON-RPC proxy built on top of ext-core.
      4
      5 Copyright:
      6     (C) Damien Churchill 2009 <damoxc@gmail.com>
      7     This program is free software; you can redistribute it and/or modify
      8     it under the terms of the GNU General Public License as published by
      9     the Free Software Foundation; either version 3, or (at your option)
     10     any later version.
     11
     12     This program is distributed in the hope that it will be useful,
     13     but WITHOUT ANY WARRANTY; without even the implied warranty of
     14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15     GNU General Public License for more details.
     16
     17     You should have received a copy of the GNU General Public License
     18     along with this program.  If not, write to:
     19         The Free Software Foundation, Inc.,
     20         51 Franklin Street, Fifth Floor
     21         Boston, MA  02110-1301, USA.
     22
     23     In addition, as a special exception, the copyright holders give
     24     permission to link the code of portions of this program with the OpenSSL
     25     library.
     26     You must obey the GNU General Public License in all respects for all of
     27     the code used other than OpenSSL. If you modify file(s) with this
     28     exception, you may extend this exception to your version of the file(s),
     29     but you are not obligated to do so. If you do not wish to do so, delete
     30     this exception statement from your version. If you delete this exception
     31     statement from all source files in the program, then also delete it here.
     32
     33 */
     34
     35 Ext.namespace('Ext.ux.util');
     36 (function() {
     37     Ext.ux.util.RpcClient = Ext.extend(Ext.util.Observable, {
     38
     39         _components: [],
     40
     41         _methods: [],
     42
     43         _requests: {},
     44
     45         _url: null,
     46
     47         _optionKeys: ['scope', 'success', 'failure'],
     48
     49         constructor: function(config) {
     50             Ext.ux.util.RpcClient.superclass.constructor.call(this, config);
     51             this._url = config.url || null;
     52             this._id = 0;
     53
     54             this.addEvents(
     55                 // raw events
     56                 /**
     57                  * @event connected
     58                  * Fires when the client has retrieved the list of methods from the server.
     59                  * @param {Ext.ux.util.RpcClient} this
     60                  */
     61                  'connected'
     62             );
     63             this.reloadMethods();
     64         },
     65
     66         reloadMethods: function() {
     67             Ext.each(this._components, function(component) {
     68                 delete this[component];
     69             }, this);
     70             this._execute('system.listMethods', {
     71                 success: this._setMethods,
     72                 scope: this
     73             });
     74         },
     75
     76         _execute: function(method, options) {
     77             options = options || {};
     78             options.params = options.params || [];
     79             options.id = this._id;
     80
     81             var request = Ext.encode({
     82                 method: method,
     83                 params: options.params,
     84                 id: options.id
     85             });
     86             this._id++;
     87
     88             return Ext.Ajax.request({
     89                 url: this._url,
     90                 method: 'POST',
     91                 success: this._onSuccess,
     92                 failure: this._onFailure,
     93                 scope: this,
     94                 jsonData: request,
     95                 options: options
     96             });
     97         },
     98
     99         _onFailure: function(response, requestOptions) {
    100             var options = requestOptions.options;
    101             errorObj = {
    102                 id: options.id,
    103                 result: null,
    104                 error: 'HTTP: ' + response.status + ' ' + response.statusText
    105             }
    106             if (Ext.type(options.failure) != 'function') return;
    107             if (options.scope) {
    108                 options.failure.call(options.scope, errorObj, response, requestOptions);
    109             } else {
    110                 options.failure(errorObj, response, requestOptions);
    111             }
    112         },
    113
    114         _onSuccess: function(response, requestOptions) {
    115             var responseObj = Ext.decode(response.responseText);
    116             var options = requestOptions.options;
    117             if (responseObj.error) {
    118                 if (Ext.type(options.failure) != 'function') return;
    119                 if (options.scope) {
    120                     options.failure.call(options.scope, responseObj, response, requestOptions);
    121                 } else {
    122                     options.failure(responseObj, response, requestOptions);
    123                 }
    124             } else {
    125                 if (Ext.type(options.success) != 'function') return;
    126                 if (options.scope) {
    127                     options.success.call(options.scope, responseObj.result, responseObj, response, requestOptions);
    128                 } else {
    129                     options.success(responseObj.result, responseObj, response, requestOptions);
    130                 }
    131             }
    132         },
    133
    134         _parseArgs: function(args) {
    135             var params = [];
    136             Ext.each(args, function(arg) {
    137                 params.push(arg);
    138             });
    139
    140             var options = params[params.length - 1];
    141             if (Ext.type(options) == 'object') {
    142                 var keys = Ext.keys(options), isOption = false;
    143
    144                 Ext.each(this._optionKeys, function(key) {
    145                     if (keys.indexOf(key) > -1) isOption = true;
    146                 });
    147
    148                 if (isOption) {
    149                     params.remove(options)
    150                 } else {
    151                     options = {}
    152                 }
    153             } else {
    154                 options = {}
    155             }
    156             options.params = params;
    157             return options;
    158         },
    159
    160         _setMethods: function(methods) {
    161             var components = {}, self = this;
    162
    163             Ext.each(methods, function(method) {
    164                 var parts = method.split('.');
    165                 var component = components[parts[0]] || {};
    166
    167                 var fn = function() {
    168                     var options = self._parseArgs(arguments);
    169                     return self._execute(method, options);
    170                 }
    171                 component[parts[1]] = fn;
    172                 components[parts[0]] = component;
    173             });
    174
    175             for (var name in components) {
    176                 self[name] = components[name];
    177             }
    178
    179             this._components = Ext.keys(components);
    180             this.fireEvent('connected', this);
    181         }
    182     });
    183 })();
    184