Project

General

Profile

Download (3.58 KB) Statistics
| Branch: | Tag: | Revision:
#--
# CyborgHood, a distributed system management software.
# Copyright (c) 2009-2010 Marc Dequènes (Duck) <Duck@DuckCorp.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++

require 'singleton'


module CyborgHood
class CyborgServerInterface
include Singleton

@split_mode_commands = []

class << self
attr_reader :split_mode_commands
end

def self.split_mode_command(*syms)
new_split_mode_commands = self.split_mode_commands || []
syms.each do |sym|
raise CyberError.new(:unrecoverable, "programmation", "not a symbol") unless sym.is_a? Symbol
raise CyberError.new(:unrecoverable, "programmation", "not an API method") unless api_method_name?(sym.to_s)
new_split_mode_commands << sym
end
instance_variable_set(:@split_mode_commands, new_split_mode_commands)
end

def self.decompose_command(cmd)
object, method = cmd.split('.', 2)

if method
begin
klass = object.split('::').inject(self) {|scope, const_name| scope.const_get(const_name)}
rescue
return
end
else
if object.index("::")
return
else
klass = self
method = cmd
end
end

[klass, method]
end

def self.is_split_mode_command?(cmd)
klass, method = decompose_command(cmd)
return false if klass.nil?

(klass.split_mode_commands || []).include? api_method_to_class_method_name(method)
end

def self.api_method_name?(method)
method =~ /^api_(.+)$/
$1
end

def self.api_method_to_class_method_name(method)
"api_#{method}".to_sym
end

def initialize
@config = Config.instance
end

def api_modules
@modules ||= self.class.constants.select do |c|
cc = self.class.const_get(c)
cc.class == Class and cc.ancestors.include? CyborgServerInterface
end
end

def api_methods
@methods ||= self.methods.collect{|m| self.class.api_method_name?(m) }.compact
end

# preliminary incoming message handling
def call(cmd, args, data)
klass, method = self.class.decompose_command(cmd)
return "551 unknown object" if klass.nil?

inst = klass.instance

unless inst.api_methods.include?(method)
return "551 this object has no such method"
end

begin
formated_data = data.to_yaml
rescue
return "552 wrong format for extra data"
end

begin
# preliminary outgoing message handling
real_method = self.class.api_method_to_class_method_name(method)
r = inst.send(real_method, *args) { formated_data }

r.to_yaml
rescue
return "550 method call failed"
end
end
end

class CyborgServerDefaultInterface < CyborgServerInterface
PROTOCOL_VERSION = "0.1~"

def api_product
PRODUCT
end

def api_version
VERSION
end

def api_protocol_version
PROTOCOL_VERSION
end

def api_bot_name
@config.bot_name
end
end
end
(1-1/2)