spqr 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +7 -1
- data/VERSION +1 -1
- data/lib/spqr/app.rb +6 -25
- data/lib/spqr/manageable.rb +38 -1
- data/ruby-spqr.spec.in +5 -0
- data/test/example-apps.rb +1 -1
- data/test/standalone-test.rb +330 -0
- metadata +10 -21
- data/examples/codegen/EchoAgent.rb +0 -33
data/CHANGES
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
version 0.3.
|
1
|
+
version 0.3.2
|
2
|
+
|
3
|
+
* far less verbose debugging information
|
4
|
+
* is_tracked declaration to automatically track instances of (non-Rhubarb) managed classes.
|
5
|
+
* SPQR now respects access annotations on property declarations. (obs. from Ian McLeod)
|
6
|
+
|
7
|
+
version 0.3.1 (e3e3729bef42fd7a5315356c85ddf30939759b34)
|
2
8
|
|
3
9
|
* "qmf_singleton" declaration for boilerplate-free singleton classes
|
4
10
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.2
|
data/lib/spqr/app.rb
CHANGED
@@ -92,6 +92,7 @@ module SPQR
|
|
92
92
|
|
93
93
|
|
94
94
|
def method_call(context, name, obj_id, args, user_id)
|
95
|
+
@log.debug("method_call(#{context.inspect}, #{name.inspect}, #{obj_id.inspect}, #{args.inspect}, #{user_id.inspect})")
|
95
96
|
begin
|
96
97
|
status = 0
|
97
98
|
message = "OK"
|
@@ -103,8 +104,6 @@ module SPQR
|
|
103
104
|
Thread.current[:qmf_user_id] = user_id
|
104
105
|
Thread.current[:qmf_context] = context
|
105
106
|
|
106
|
-
@log.debug "calling method: context=#{context} method=#{name} object_id=#{obj_id}, user=#{user_id}"
|
107
|
-
|
108
107
|
managed_object = find_object(context, class_id, obj_id)
|
109
108
|
@log.debug("managed object is #{managed_object}")
|
110
109
|
managed_method = managed_object.class.spqr_meta.mmethods[name.to_sym]
|
@@ -112,15 +111,8 @@ module SPQR
|
|
112
111
|
raise RuntimeError.new("#{managed_object.class} does not have #{name} exposed as a manageable method; has #{managed_object.class.spqr_meta.mmethods.inspect}") unless managed_method
|
113
112
|
|
114
113
|
# Extract actual parameters from the Qmf::Arguments structure into a proper ruby list
|
115
|
-
@log.debug("actual params are: #{args.instance_variable_get(:@by_hash).inspect}") rescue nil
|
116
114
|
actuals_in = managed_method.formals_in.inject([]) {|acc,nm| acc << args[nm]}
|
117
115
|
actual_count = actuals_in.size
|
118
|
-
|
119
|
-
@log.debug("managed_object.respond_to? #{managed_method.name.to_sym} ==> #{managed_object.respond_to? managed_method.name.to_sym}")
|
120
|
-
@log.debug("managed_object.class.spqr_meta.mmethods.include? #{name.to_sym} ==> #{managed_object.class.spqr_meta.mmethods.include? name.to_sym}")
|
121
|
-
@log.debug("formals: #{managed_method.formals_in.inspect}")
|
122
|
-
@log.debug("actuals: #{actuals_in.inspect}")
|
123
|
-
|
124
116
|
actuals_out = []
|
125
117
|
|
126
118
|
begin
|
@@ -133,7 +125,7 @@ module SPQR
|
|
133
125
|
raise RuntimeError.new("#{managed_object.class} did not return the appropriate number of return values; got '#{actuals_out.inspect}', but expected #{managed_method.types_out.inspect}") unless result_valid(actuals_out, managed_method)
|
134
126
|
|
135
127
|
rescue ::SPQR::ManageableObjectError => failure
|
136
|
-
@log.
|
128
|
+
@log.warn "#{name} called SPQR::Manageable#fail: #{failure}"
|
137
129
|
status = failure.status
|
138
130
|
message = failure.message || "ERROR"
|
139
131
|
# XXX: failure.result is currently ignored
|
@@ -146,9 +138,6 @@ module SPQR
|
|
146
138
|
elsif managed_method.formals_out.size == 1
|
147
139
|
actuals_out = [actuals_out] # wrap this up in a list
|
148
140
|
end
|
149
|
-
|
150
|
-
@log.debug("formals_out == #{managed_method.formals_out.inspect}")
|
151
|
-
@log.debug("actuals_out == #{actuals_out.inspect}")
|
152
141
|
|
153
142
|
unless failed
|
154
143
|
# Copy any out parameters from return value to the
|
@@ -169,7 +158,7 @@ module SPQR
|
|
169
158
|
end
|
170
159
|
|
171
160
|
def get_query(context, query, user_id)
|
172
|
-
@log.debug "
|
161
|
+
@log.debug "get_query: user=#{user_id} context=#{context} class=#{query.class_name} object_num=#{query.object_id && query.object_id.object_num_low} details=#{query}"
|
173
162
|
|
174
163
|
cmeta = @classes_by_name[query.class_name]
|
175
164
|
objs = []
|
@@ -188,11 +177,10 @@ module SPQR
|
|
188
177
|
end
|
189
178
|
|
190
179
|
objs.each do |obj|
|
191
|
-
@log.debug("query_response of: #{obj.inspect}")
|
192
180
|
@agent.query_response(context, obj) rescue @log.error($!.inspect)
|
193
181
|
end
|
194
182
|
|
195
|
-
@log.debug("completing query
|
183
|
+
@log.debug("completing query; returned #{objs.size} objects")
|
196
184
|
@agent.query_complete(context)
|
197
185
|
end
|
198
186
|
|
@@ -264,9 +252,7 @@ module SPQR
|
|
264
252
|
|
265
253
|
def find_object(ctx, c_id, obj_id)
|
266
254
|
# XXX: context is currently ignored
|
267
|
-
@log.debug("in find_object; class ID is #{c_id}, object ID is #{obj_id}...")
|
268
255
|
klass = @classes_by_id[c_id]
|
269
|
-
@log.debug("found class #{klass.inspect}")
|
270
256
|
klass.find_by_id(obj_id) if klass
|
271
257
|
end
|
272
258
|
|
@@ -317,6 +303,7 @@ module SPQR
|
|
317
303
|
collection.each do |basic|
|
318
304
|
basic_name = basic.name.to_s
|
319
305
|
basic_type = get_xml_constant(basic.kind.to_s, ::SPQR::XmlConstants::Type)
|
306
|
+
basic.options[:access] = get_xml_constant(basic.options[:access].to_s.upcase, ::SPQR::XmlConstants::Access) if basic.options[:access]
|
320
307
|
@log.debug("+-- creating a QMF schema for #{what} #{basic_name} (#{basic_type}) with options #{basic.options.inspect}")
|
321
308
|
sc.send(msg, klass.new(basic_name, basic_type, basic.options))
|
322
309
|
end
|
@@ -326,7 +313,7 @@ module SPQR
|
|
326
313
|
|
327
314
|
# turns an instance of a managed object into a QmfObject
|
328
315
|
def qmfify(obj)
|
329
|
-
@log.debug("
|
316
|
+
@log.debug("qmfify: treating instance of #{obj.class.name}: qmf_oid is #{obj.qmf_oid} and class_id is #{obj.class.class_id}")
|
330
317
|
cm = @classes_by_name[obj.class.spqr_meta.classname.to_s]
|
331
318
|
return nil unless cm
|
332
319
|
|
@@ -334,13 +321,8 @@ module SPQR
|
|
334
321
|
|
335
322
|
set_attrs(qmfobj, obj)
|
336
323
|
|
337
|
-
@log.debug("calling alloc_object_id(#{obj.qmf_oid}, #{obj.class.class_id})")
|
338
324
|
oid = @agent.alloc_object_id(obj.qmf_oid, obj.class.class_id)
|
339
|
-
|
340
|
-
@log.debug("calling qmfobj.set_object_id(#{oid})")
|
341
325
|
qmfobj.set_object_id(oid)
|
342
|
-
|
343
|
-
@log.debug("returning from qmfify")
|
344
326
|
qmfobj
|
345
327
|
end
|
346
328
|
|
@@ -351,7 +333,6 @@ module SPQR
|
|
351
333
|
|
352
334
|
attrs.each do |a|
|
353
335
|
getter = a.name.to_s
|
354
|
-
@log.debug("setting property/statistic #{getter} to its value from #{o}: #{o.send(getter) if o.respond_to?(getter)}")
|
355
336
|
value = o.send(getter) if o.respond_to?(getter)
|
356
337
|
|
357
338
|
if value || a.kind == :bool
|
data/lib/spqr/manageable.rb
CHANGED
@@ -159,7 +159,9 @@ module SPQR
|
|
159
159
|
spqr_meta.declare_method(name, description, options, blk)
|
160
160
|
end
|
161
161
|
|
162
|
-
|
162
|
+
# Declares that this class is a singleton class; that is, only one
|
163
|
+
# instance will be published over QMF
|
164
|
+
def is_singleton
|
163
165
|
def self.instances
|
164
166
|
@instances ||= [self.new]
|
165
167
|
end
|
@@ -173,6 +175,40 @@ module SPQR
|
|
173
175
|
end
|
174
176
|
end
|
175
177
|
|
178
|
+
# Declares that instances of this class will automatically be
|
179
|
+
# tracked (and find_all and find_by_id methods generated).
|
180
|
+
# Instances of automatically-tracked classes must be explicitly
|
181
|
+
# deleted (with the delete class method). Do not use automatic
|
182
|
+
# tracking with Rhubarb, which automatically tracks instances for
|
183
|
+
# you.
|
184
|
+
def is_tracked
|
185
|
+
# no pun intended, I promise
|
186
|
+
alias_method :old_new, :new
|
187
|
+
|
188
|
+
def self.instances
|
189
|
+
@instances ||= {}
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.find_all
|
193
|
+
instances.values
|
194
|
+
end
|
195
|
+
|
196
|
+
def self.find_by_id(id)
|
197
|
+
instances[id]
|
198
|
+
end
|
199
|
+
|
200
|
+
# XXX: would it make more sense to call allocate and initialize explicitly?
|
201
|
+
def self.new(*args)
|
202
|
+
result = old_new(*args)
|
203
|
+
instances[result.qmf_oid] = result
|
204
|
+
result
|
205
|
+
end
|
206
|
+
|
207
|
+
def self.delete(instance)
|
208
|
+
instances.delete(instance.qmf_oid)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
176
212
|
def qmf_package_name(nm)
|
177
213
|
spqr_meta.package = nm
|
178
214
|
end
|
@@ -294,6 +330,7 @@ module SPQR
|
|
294
330
|
def self.included(other)
|
295
331
|
class << other
|
296
332
|
include ManageableClassMixins
|
333
|
+
alias_method :qmf_singleton, :is_singleton
|
297
334
|
end
|
298
335
|
|
299
336
|
unless other.respond_to? :find_by_id
|
data/ruby-spqr.spec.in
CHANGED
@@ -70,6 +70,11 @@ rm -rf %{buildroot}
|
|
70
70
|
|
71
71
|
%changelog
|
72
72
|
|
73
|
+
* Wed Sep 15 2010 <willb@redhat> - 0.3.2-1
|
74
|
+
- updated to version 0.3.2-1
|
75
|
+
- removed spurious debugging output
|
76
|
+
- access modifiers now respected on properties
|
77
|
+
|
73
78
|
* Mon May 10 2010 <willb@redhat> - 0.3.0-1
|
74
79
|
- updated to version 0.3.0-1
|
75
80
|
|
data/test/example-apps.rb
CHANGED
@@ -0,0 +1,330 @@
|
|
1
|
+
require 'qmf'
|
2
|
+
|
3
|
+
class App < Qmf::AgentHandler
|
4
|
+
class ClassMeta < Struct.new(:object_class, :schema_class) ; end
|
5
|
+
|
6
|
+
attr_reader :agent
|
7
|
+
|
8
|
+
def initialize(options=nil)
|
9
|
+
defaults = {:logfile=>STDERR, :loglevel=>Logger::WARN, :notifier=>nil, :server=>"localhost", :port=>5672}
|
10
|
+
|
11
|
+
# convenient shorthands for log levels
|
12
|
+
loglevels = {:debug => Logger::DEBUG, :info => Logger::INFO, :warn => Logger::WARN, :error => Logger::ERROR, :fatal => Logger::FATAL}
|
13
|
+
|
14
|
+
options = defaults unless options
|
15
|
+
|
16
|
+
# set unsupplied options to defaults
|
17
|
+
defaults.each do |k,v|
|
18
|
+
options[k] = v unless options[k]
|
19
|
+
end
|
20
|
+
|
21
|
+
# fix up shorthands
|
22
|
+
options[:loglevel] = loglevels[options[:loglevel]] if loglevels[options[:loglevel]]
|
23
|
+
|
24
|
+
logger_opts = ([options[:logfile]] + [options[:logoptions]]).flatten.compact
|
25
|
+
|
26
|
+
@log = Logger.new(*logger_opts)
|
27
|
+
@log.level = options[:loglevel]
|
28
|
+
|
29
|
+
@log.info("initializing SPQR app....")
|
30
|
+
|
31
|
+
@classes_by_name = {}
|
32
|
+
@classes_by_id = {}
|
33
|
+
@pipe = options[:notifier]
|
34
|
+
@app_name = (options[:appname] or "SPQR application [#{Process.pid}]")
|
35
|
+
@qmf_host = options[:server]
|
36
|
+
@qmf_port = options[:port]
|
37
|
+
@qmf_sendUserId = if options.has_key?(:send_user_id)
|
38
|
+
options[:send_user_id]
|
39
|
+
else
|
40
|
+
(options.has_key?(:user) || options.has_key?(:password))
|
41
|
+
end
|
42
|
+
|
43
|
+
@qmf_user = options[:user]
|
44
|
+
@qmf_password = options[:password]
|
45
|
+
end
|
46
|
+
|
47
|
+
def register(*ks)
|
48
|
+
manageable_ks = ks.select {|kl| manageable? kl}
|
49
|
+
unmanageable_ks = ks.select {|kl| not manageable? kl}
|
50
|
+
manageable_ks.each do |klass|
|
51
|
+
schemaclass = schematize(klass)
|
52
|
+
|
53
|
+
klass.log = @log
|
54
|
+
|
55
|
+
# XXX
|
56
|
+
if klass.included_modules.include?(::SPQR::Manageable)
|
57
|
+
@classes_by_id[klass.class_id] = klass
|
58
|
+
@classes_by_name[klass.spqr_meta.classname.to_s] = ClassMeta.new(klass, schemaclass)
|
59
|
+
else
|
60
|
+
@log.info "NOT registering query/lookup info for #{klass}; is it an event class?"
|
61
|
+
end
|
62
|
+
|
63
|
+
@log.info("SETTING #{klass.spqr_meta.classname}.app to #{self.inspect}")
|
64
|
+
klass.app = self
|
65
|
+
end
|
66
|
+
|
67
|
+
unmanageable_ks.each do |klass|
|
68
|
+
@log.warn("SPQR can't manage #{klass}, which was registered")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
def method_call(context, name, obj_id, args, user_id)
|
74
|
+
begin
|
75
|
+
status = 0
|
76
|
+
message = "OK"
|
77
|
+
failed = false
|
78
|
+
|
79
|
+
class_id = obj_id.object_num_high
|
80
|
+
obj_id = obj_id.object_num_low
|
81
|
+
|
82
|
+
Thread.current[:qmf_user_id] = user_id
|
83
|
+
Thread.current[:qmf_context] = context
|
84
|
+
|
85
|
+
@log.debug "calling method: context=#{context} method=#{name} object_id=#{obj_id}, user=#{user_id}"
|
86
|
+
|
87
|
+
managed_object = find_object(context, class_id, obj_id)
|
88
|
+
@log.debug("managed object is #{managed_object}")
|
89
|
+
managed_method = managed_object.class.spqr_meta.mmethods[name.to_sym]
|
90
|
+
|
91
|
+
raise RuntimeError.new("#{managed_object.class} does not have #{name} exposed as a manageable method; has #{managed_object.class.spqr_meta.mmethods.inspect}") unless managed_method
|
92
|
+
|
93
|
+
# Extract actual parameters from the Qmf::Arguments structure into a proper ruby list
|
94
|
+
@log.debug("actual params are: #{args.instance_variable_get(:@by_hash).inspect}") rescue nil
|
95
|
+
actuals_in = managed_method.formals_in.inject([]) {|acc,nm| acc << args[nm]}
|
96
|
+
actual_count = actuals_in.size
|
97
|
+
|
98
|
+
@log.debug("managed_object.respond_to? #{managed_method.name.to_sym} ==> #{managed_object.respond_to? managed_method.name.to_sym}")
|
99
|
+
@log.debug("managed_object.class.spqr_meta.mmethods.include? #{name.to_sym} ==> #{managed_object.class.spqr_meta.mmethods.include? name.to_sym}")
|
100
|
+
@log.debug("formals: #{managed_method.formals_in.inspect}")
|
101
|
+
@log.debug("actuals: #{actuals_in.inspect}")
|
102
|
+
|
103
|
+
actuals_out = []
|
104
|
+
|
105
|
+
begin
|
106
|
+
actuals_out = case actual_count
|
107
|
+
when 0 then managed_object.send(name.to_sym)
|
108
|
+
when 1 then managed_object.send(name.to_sym, actuals_in[0])
|
109
|
+
else managed_object.send(name.to_sym, *actuals_in)
|
110
|
+
end
|
111
|
+
|
112
|
+
raise RuntimeError.new("#{managed_object.class} did not return the appropriate number of return values; got '#{actuals_out.inspect}', but expected #{managed_method.types_out.inspect}") unless result_valid(actuals_out, managed_method)
|
113
|
+
|
114
|
+
rescue ::SPQR::ManageableObjectError => failure
|
115
|
+
@log.info "#{name} called SPQR::Manageable#fail: #{failure}"
|
116
|
+
status = failure.status
|
117
|
+
message = failure.message || "ERROR"
|
118
|
+
# XXX: failure.result is currently ignored
|
119
|
+
actuals_out = failure.result || managed_method.formals_out.inject([]) {|acc, val| acc << args[val]; acc}
|
120
|
+
failed = true
|
121
|
+
end
|
122
|
+
|
123
|
+
if managed_method.formals_out.size == 0
|
124
|
+
actuals_out = [] # ignore return value in this case
|
125
|
+
elsif managed_method.formals_out.size == 1
|
126
|
+
actuals_out = [actuals_out] # wrap this up in a list
|
127
|
+
end
|
128
|
+
|
129
|
+
@log.debug("formals_out == #{managed_method.formals_out.inspect}")
|
130
|
+
@log.debug("actuals_out == #{actuals_out.inspect}")
|
131
|
+
|
132
|
+
unless failed
|
133
|
+
# Copy any out parameters from return value to the
|
134
|
+
# Qmf::Arguments structure; see XXX above
|
135
|
+
managed_method.formals_out.zip(actuals_out).each do |k,v|
|
136
|
+
@log.debug("fixing up out params: #{k.inspect} --> #{v.inspect}")
|
137
|
+
encoded_val = encode_object(v)
|
138
|
+
args[k] = encoded_val
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
@agent.method_response(context, status, message, args)
|
143
|
+
rescue Exception => ex
|
144
|
+
@log.error "Error calling #{name}: #{ex}"
|
145
|
+
@log.error " " + ex.backtrace.join("\n ")
|
146
|
+
@agent.method_response(context, 1, "ERROR: #{ex}", args)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_query(context, query, user_id)
|
151
|
+
@log.debug "query: user=#{user_id} context=#{context} class=#{query.class_name} object_num=#{query.object_id.object_num_low if query.object_id} details=#{query} haveSelect=#{query.impl and query.impl.haveSelect} getSelect=#{query.impl and query.impl.getSelect} (#{query.impl and query.impl.getSelect and query.impl.getSelect.methods.inspect})"
|
152
|
+
|
153
|
+
cmeta = @classes_by_name[query.class_name]
|
154
|
+
objs = []
|
155
|
+
|
156
|
+
# XXX: are these cases mutually exclusive?
|
157
|
+
|
158
|
+
# handle queries for a certain class
|
159
|
+
if cmeta
|
160
|
+
objs = objs + cmeta.object_class.find_all.collect {|obj| qmfify(obj)}
|
161
|
+
end
|
162
|
+
|
163
|
+
# handle queries for a specific object
|
164
|
+
o = find_object(context, query.object_id.object_num_high, query.object_id.object_num_low) rescue nil
|
165
|
+
if o
|
166
|
+
objs << qmfify(o)
|
167
|
+
end
|
168
|
+
|
169
|
+
objs.each do |obj|
|
170
|
+
@log.debug("query_response of: #{obj.inspect}")
|
171
|
+
@agent.query_response(context, obj) rescue @log.error($!.inspect)
|
172
|
+
end
|
173
|
+
|
174
|
+
@log.debug("completing query....")
|
175
|
+
@agent.query_complete(context)
|
176
|
+
end
|
177
|
+
|
178
|
+
def main
|
179
|
+
settings = Qmf::ConnectionSettings.new
|
180
|
+
settings.host = @qmf_host
|
181
|
+
settings.port = @qmf_port
|
182
|
+
settings.sendUserId = @qmf_sendUserId
|
183
|
+
|
184
|
+
settings.username = @qmf_user if @qmf_sendUserId
|
185
|
+
settings.password = @qmf_password if @qmf_sendUserId
|
186
|
+
|
187
|
+
@schemaclass = Qmf::SchemaObjectClass.new("test", "testclass")
|
188
|
+
|
189
|
+
@connection = Qmf::Connection.new(settings)
|
190
|
+
@log.debug(" +-- @connection created: #{@connection}")
|
191
|
+
@log.debug(" +-- app name is '#{@app_name}'")
|
192
|
+
|
193
|
+
@agent = Qmf::Agent.new(self, @app_name)
|
194
|
+
@log.debug(" +-- @agent created: #{@agent}")
|
195
|
+
|
196
|
+
@agent.set_connection(@connection)
|
197
|
+
@log.debug(" +-- @agent.set_connection called")
|
198
|
+
|
199
|
+
@log.debug(" +-- registering classes...")
|
200
|
+
@classes_by_name.values.each do |km|
|
201
|
+
@agent.register_class(km.schema_class)
|
202
|
+
@log.debug(" +--+-- #{km.schema_class.package_name} #{km.schema_class.class_name} registered")
|
203
|
+
end
|
204
|
+
|
205
|
+
@log.debug("entering orbit....")
|
206
|
+
|
207
|
+
sleep
|
208
|
+
end
|
209
|
+
|
210
|
+
private
|
211
|
+
|
212
|
+
def result_valid(actuals, mm)
|
213
|
+
(actuals.kind_of?(Array) and mm.formals_out.size == actuals.size) or mm.formals_out.size <= 1
|
214
|
+
end
|
215
|
+
|
216
|
+
def qmf_arguments_to_hash(args)
|
217
|
+
result = {}
|
218
|
+
args.each do |k,v|
|
219
|
+
result[k] = v
|
220
|
+
end
|
221
|
+
result
|
222
|
+
end
|
223
|
+
|
224
|
+
def encode_object(o)
|
225
|
+
return o unless o.kind_of? ::SPQR::Manageable
|
226
|
+
@agent.alloc_object_id(*(o.qmf_id))
|
227
|
+
end
|
228
|
+
|
229
|
+
def find_object(ctx, c_id, obj_id)
|
230
|
+
# XXX: context is currently ignored
|
231
|
+
@log.debug("in find_object; class ID is #{c_id}, object ID is #{obj_id}...")
|
232
|
+
klass = @classes_by_id[c_id]
|
233
|
+
@log.debug("found class #{klass.inspect}")
|
234
|
+
klass.find_by_id(obj_id) if klass
|
235
|
+
end
|
236
|
+
|
237
|
+
def schematize(klass)
|
238
|
+
@log.info("Making a QMF schema for #{klass.spqr_meta.classname}")
|
239
|
+
|
240
|
+
if klass.respond_to? :schematize
|
241
|
+
@log.info("#{klass.spqr_meta.classname} knows how to schematize itself; it's probably an event class")
|
242
|
+
return klass.schematize
|
243
|
+
else
|
244
|
+
@log.info("#{klass.spqr_meta.classname} doesn't know how to schematize itself; it's probably an object class")
|
245
|
+
return schematize_object_class(klass)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def schematize_object_class(klass)
|
250
|
+
meta = klass.spqr_meta
|
251
|
+
package = meta.package.to_s
|
252
|
+
classname = meta.classname.to_s
|
253
|
+
@log.info("+-- class #{classname} is in package #{package}")
|
254
|
+
|
255
|
+
sc = Qmf::SchemaObjectClass.new(package, classname)
|
256
|
+
|
257
|
+
meta.manageable_methods.each do |mm|
|
258
|
+
@log.info("+-- creating a QMF schema for method #{mm}")
|
259
|
+
m_opts = mm.options
|
260
|
+
m_opts[:desc] ||= mm.description if mm.description
|
261
|
+
|
262
|
+
method = Qmf::SchemaMethod.new(mm.name.to_s, m_opts)
|
263
|
+
|
264
|
+
mm.args.each do |arg|
|
265
|
+
@log.info("| +-- creating a QMF schema for arg #{arg}")
|
266
|
+
|
267
|
+
encode_argument(arg, method)
|
268
|
+
end
|
269
|
+
|
270
|
+
sc.add_method(method)
|
271
|
+
end
|
272
|
+
|
273
|
+
add_attributes(sc, meta.properties, :add_property, Qmf::SchemaProperty)
|
274
|
+
add_attributes(sc, meta.statistics, :add_statistic, Qmf::SchemaStatistic)
|
275
|
+
|
276
|
+
sc
|
277
|
+
end
|
278
|
+
|
279
|
+
def add_attributes(sc, collection, msg, klass, what=nil)
|
280
|
+
what ||= (msg.to_s.split("_").pop rescue "property or statistic")
|
281
|
+
collection.each do |basic|
|
282
|
+
basic_name = basic.name.to_s
|
283
|
+
basic_type = get_xml_constant(basic.kind.to_s, ::SPQR::XmlConstants::Type)
|
284
|
+
@log.debug("+-- creating a QMF schema for #{what} #{basic_name} (#{basic_type}) with options #{basic.options.inspect}")
|
285
|
+
sc.send(msg, klass.new(basic_name, basic_type, basic.options))
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
include ::SPQR::Util
|
290
|
+
|
291
|
+
# turns an instance of a managed object into a QmfObject
|
292
|
+
def qmfify(obj)
|
293
|
+
@log.debug("trying to qmfify #{obj}: qmf_oid is #{obj.qmf_oid} and class_id is #{obj.class.class_id}")
|
294
|
+
cm = @classes_by_name[obj.class.spqr_meta.classname.to_s]
|
295
|
+
return nil unless cm
|
296
|
+
|
297
|
+
qmfobj = Qmf::AgentObject.new(cm.schema_class)
|
298
|
+
|
299
|
+
set_attrs(qmfobj, obj)
|
300
|
+
|
301
|
+
@log.debug("calling alloc_object_id(#{obj.qmf_oid}, #{obj.class.class_id})")
|
302
|
+
oid = @agent.alloc_object_id(obj.qmf_oid, obj.class.class_id)
|
303
|
+
|
304
|
+
@log.debug("calling qmfobj.set_object_id(#{oid})")
|
305
|
+
qmfobj.set_object_id(oid)
|
306
|
+
|
307
|
+
@log.debug("returning from qmfify")
|
308
|
+
qmfobj
|
309
|
+
end
|
310
|
+
|
311
|
+
def set_attrs(qo, o)
|
312
|
+
return unless o.class.respond_to? :spqr_meta
|
313
|
+
|
314
|
+
attrs = o.class.spqr_meta.properties + o.class.spqr_meta.statistics
|
315
|
+
|
316
|
+
attrs.each do |a|
|
317
|
+
getter = a.name.to_s
|
318
|
+
@log.debug("setting property/statistic #{getter} to its value from #{o}: #{o.send(getter) if o.respond_to?(getter)}")
|
319
|
+
value = o.send(getter) if o.respond_to?(getter)
|
320
|
+
|
321
|
+
if value || a.kind == :bool
|
322
|
+
# XXX: remove this line when/if Manageable includes an
|
323
|
+
# appropriate impl method
|
324
|
+
value = encode_object(value) if value.kind_of?(::SPQR::Manageable)
|
325
|
+
qo[getter] = value
|
326
|
+
end
|
327
|
+
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
metadata
CHANGED
@@ -1,12 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spqr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
segments:
|
6
|
-
- 0
|
7
|
-
- 3
|
8
|
-
- 1
|
9
|
-
version: 0.3.1
|
4
|
+
version: 0.3.2
|
10
5
|
platform: ruby
|
11
6
|
authors:
|
12
7
|
- William Benton
|
@@ -14,23 +9,19 @@ autorequire:
|
|
14
9
|
bindir: bin
|
15
10
|
cert_chain: []
|
16
11
|
|
17
|
-
date: 2010-
|
12
|
+
date: 2010-09-15 00:00:00 -05:00
|
18
13
|
default_executable: spqr-gen.rb
|
19
14
|
dependencies:
|
20
15
|
- !ruby/object:Gem::Dependency
|
21
16
|
name: rspec
|
22
|
-
|
23
|
-
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
20
|
requirements:
|
25
21
|
- - ">="
|
26
22
|
- !ruby/object:Gem::Version
|
27
|
-
segments:
|
28
|
-
- 1
|
29
|
-
- 2
|
30
|
-
- 9
|
31
23
|
version: 1.2.9
|
32
|
-
|
33
|
-
version_requirements: *id001
|
24
|
+
version:
|
34
25
|
description: SPQR makes it very simple to expose methods on Ruby objects over QMF. You must install ruby-qmf in order to use SPQR.
|
35
26
|
email: willb@redhat.com
|
36
27
|
executables:
|
@@ -92,20 +83,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
83
|
requirements:
|
93
84
|
- - ">="
|
94
85
|
- !ruby/object:Gem::Version
|
95
|
-
segments:
|
96
|
-
- 0
|
97
86
|
version: "0"
|
87
|
+
version:
|
98
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
89
|
requirements:
|
100
90
|
- - ">="
|
101
91
|
- !ruby/object:Gem::Version
|
102
|
-
segments:
|
103
|
-
- 0
|
104
92
|
version: "0"
|
93
|
+
version:
|
105
94
|
requirements: []
|
106
95
|
|
107
96
|
rubyforge_project:
|
108
|
-
rubygems_version: 1.3.
|
97
|
+
rubygems_version: 1.3.5
|
109
98
|
signing_key:
|
110
99
|
specification_version: 3
|
111
100
|
summary: "SPQR: {Schema Processor|Straightforward Publishing} for QMF agents in Ruby"
|
@@ -120,11 +109,11 @@ test_files:
|
|
120
109
|
- test/helper.rb
|
121
110
|
- test/test_failbot.rb
|
122
111
|
- test/test_spqr_boolprop.rb
|
112
|
+
- test/standalone-test.rb
|
123
113
|
- test/test_spqr_clicker.rb
|
124
114
|
- test/test_spqr_integerprop.rb
|
125
115
|
- test/test_user_and_context.rb
|
126
116
|
- test/test_spqr_hello.rb
|
127
117
|
- examples/logdaemon.rb
|
128
118
|
- examples/hello.rb
|
129
|
-
- examples/codegen/EchoAgent.rb
|
130
119
|
- examples/logservice.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Examples
|
2
|
-
module Codegen
|
3
|
-
class EchoAgent
|
4
|
-
include SPQR::Manageable
|
5
|
-
|
6
|
-
spqr_package 'examples.codegen'
|
7
|
-
spqr_class 'EchoAgent'
|
8
|
-
# Find method (NB: you must implement this)
|
9
|
-
def EchoAgent.find_by_id(objid)
|
10
|
-
EchoAgent.new
|
11
|
-
end
|
12
|
-
# Find-all method (NB: you must implement this)
|
13
|
-
def EchoAgent.find_all
|
14
|
-
[EchoAgent.new]
|
15
|
-
end
|
16
|
-
### Schema method declarations
|
17
|
-
|
18
|
-
# echo returns its argument
|
19
|
-
# * arg (lstr/IO)
|
20
|
-
#
|
21
|
-
def echo(args)
|
22
|
-
# Print values of in/out parameters
|
23
|
-
log.debug "arg => #{args["arg"]}" #
|
24
|
-
# Assign values to in/out parameters
|
25
|
-
args["arg"] = args["arg"]
|
26
|
-
end
|
27
|
-
|
28
|
-
spqr_expose :echo do |args|
|
29
|
-
args.declare :arg, :lstr, :inout, {}
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|