Class: Emissary::Identity

Inherits:
Object show all
Defined in:
lib/emissary/identity.rb

Direct Known Subclasses

Ec2, Unix

Defined Under Namespace

Classes: Ec2, Unix

Constant Summary collapse

INTERNAL_IDENTITY_GLOB =
::File.join(Emissary::LIBPATH, 'emissary', 'identity', '*.rb')
EXTERNAL_IDENTITY_GLOB =
::File.join(Emissary::EXTERNAL_IDENTITIES, '*.rb')

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeIdentity

Returns a new instance of Identity.



30
31
32
33
34
# File 'lib/emissary/identity.rb', line 30

def initialize
  @loaded     = false
  @methods    = nil
  @identities = nil
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Object

Delegation Factory - Uses registered high priority subclasses for delegation of method calls, falling back to lower priority subclasess when the method isn’t available or throws a :pass in the higher priority subclass



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/emissary/identity.rb', line 63

def method_missing name, *args
  # don't perform lookups on subclasses
  super name, *args unless self.class == Emissary::Identity
  
  name = name.to_sym
  unless (@methods||={}).has_key? name
    method_delegate = value = nil

    # loop through each possible identity, higher priority identities
    # first (0 == low, > 0 == higher). 
    identities.each do |id,object|
      value = nil
      if object.respond_to?(name)
        method_delegate = catch(:pass) {
          value = object.__send__(name, *args) # test for :pass request
          object
        }
        break unless method_delegate.nil?
      end
    end
    
    # if we've gone through all the possible delegates, then pass it
    # up to the superclass (in this case, Object)
    if method_delegate.nil?
      return super(name, *args)
    end
    
    @methods[name] = method_delegate
    return value
  end
 
  return @methods[name].__send__(name, *args)
end

Instance Attribute Details

#loadedObject (readonly) Also known as: loaded?

Returns the value of attribute loaded.



25
26
27
# File 'lib/emissary/identity.rb', line 25

def loaded
  @loaded
end

#methodsObject (readonly)

Returns the value of attribute methods.



25
26
27
# File 'lib/emissary/identity.rb', line 25

def methods
  @methods
end

Class Method Details

.exclude(names) ⇒ Object



109
110
111
112
# File 'lib/emissary/identity.rb', line 109

def self.exclude names
  @@exclusions ||= []
  @@exclusions |= (names.is_a?(String) ? names.split(/\s*,\s*/) : names.to_a.collect { |n| n.to_s.to_sym })
end

.exclusionsObject

Exclude an identity type when delegating identity method calls



116
117
118
119
# File 'lib/emissary/identity.rb', line 116

def self.exclusions
  @@exclusions ||= []
  @@exclusions.to_a.map! { |e| e.to_sym }
end

.instanceObject



36
37
38
# File 'lib/emissary/identity.rb', line 36

def self.instance
  @@instance ||= self.new
end

.new(*largs) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/emissary/identity.rb', line 40

def self.new(*largs)
  # prevent subclasses from being instantiated directly, except through
  # the identities() method of this parent class. This class is just a
  # simple method factory and the children shouldn't need to be accessed
  # except through the interface provided here.
  if self == Emissary::Identity
    raise Exception, "Cannot instantiate singleton class directly - use #{self.name}#instance" unless __caller__ == :instance
  else
    klass = self.name.split(/::/)[0..-2].join '::'; subklass = self.name.split(/::/).last
    raise Exception, "Cannot instantiate '#{klass}' subclass '#{subklass}' directly" unless __caller__ == :identities
  end

  allocate.instance_eval(<<-EOS, __FILE__, __LINE__)
    load_identities unless self.class != Emissary::Identity
    self
  EOS
end

.register(name, opts = {}) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/emissary/identity.rb', line 97

def self.register name, opts = {}
  priority = if name != :unix
    opts[:priority].to_i > 0 ? opts.delete(:priority).to_i : 1
  else
    # unix identity always gets zero - though this locks us
    # into *nix as our base. XXX maybe rethink this?
    0 
  end
  
  (self.registry[priority] ||= [])  << name
end

Instance Method Details

#identifiersObject

Retrieve a list of all the available identifers through reflection of the subclasses



130
131
132
133
134
# File 'lib/emissary/identity.rb', line 130

def identifiers
  identities.inject([]) do |list,(id,object)|
    list |= object.public_methods - object.class.superclass.public_methods - self.public_methods;  list
  end.sort.collect { |id| id.to_sym }
end

#to_hObject

Retreive a hash of all identifiers and their values



138
139
140
# File 'lib/emissary/identity.rb', line 138

def to_h
  Hash[(identifiers).zip(identifiers.collect { |identifier| self.send(identifier) })]
end

#to_sObject



121
122
123
124
125
126
# File 'lib/emissary/identity.rb', line 121

def to_s
  s = ''
  s << '#<%s:0x%x ' % [ self.class, self.__id__ * 2]
  s << to_h.inject([]) { |a,(k,v)| a << %Q|@#{k}="#{v}"| }.join(', ')
  s << '>'
end