      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
    105             }
    106             if (Ext.type(options.failure) != 'function') return;
    107             if (options.scope) {
    108                 options.failure.call(options.scope, responseObj.error, responseObj, response);
    109             } else {
    110                 options.failure(responseObj.error, responseObj, response);
    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.error, responseObj, response, requestOptions);
    121                 } else {
    122                     options.failure(responseObj.error, 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