lib/openwfe/expressions/rprocdef.rb in ruote-0.9.18 vs lib/openwfe/expressions/rprocdef.rb in ruote-0.9.19

- old
+ new

@@ -1,375 +1,370 @@ # #-- # Copyright (c) 2007-2008, John Mettraux, OpenWFE.org # All rights reserved. -# -# Redistribution and use in source and binary forms, with or without +# +# Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: -# +# # . Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# . Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation +# list of conditions and the following disclaimer. +# +# . Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. -# +# # . Neither the name of the "OpenWFE" nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. #++ # # # "made in Japan" # # John Mettraux at openwfe.org # -require 'rufus/eval' # gem 'rufus-eval' - +require 'openwfe/util/treechecker' require 'openwfe/utils' require 'openwfe/expressions/raw' module OpenWFE - # - # Extend this class to create a programmatic process definition. - # - # A short example : - # - # class MyProcessDefinition < OpenWFE::ProcessDefinition - # def make - # process_definition :name => "test1", :revision => "0" do - # sequence do - # set :variable => "toto", :value => "nada" - # print "toto:${toto}" - # end - # end - # end - # end - # - # li = OpenWFE::LaunchItem.new(MyProcessDefinition) - # engine.launch(li) - # - # - class ProcessDefinition + # + # Extend this class to create a programmatic process definition. + # + # A short example : + # + # class MyProcessDefinition < OpenWFE::ProcessDefinition + # def make + # process_definition :name => "test1", :revision => "0" do + # sequence do + # set :variable => "toto", :value => "nada" + # print "toto:${toto}" + # end + # end + # end + # end + # + # li = OpenWFE::LaunchItem.new(MyProcessDefinition) + # engine.launch(li) + # + # + class ProcessDefinition - def self.metaclass; class << self; self; end; end + def self.metaclass; class << self; self; end; end - attr_reader :context + attr_reader :context - def initialize + def initialize - super() - @context = Context.new - end + super() + @context = Context.new + end - def method_missing (m, *args, &block) + def method_missing (m, *args, &block) - #puts "__i_method_missing >>>#{m}<<<<" + #puts "__i_method_missing >>>#{m}<<<<" - ProcessDefinition.make_expression( - @context, - OpenWFE::to_expression_name(m), - ProcessDefinition.pack_args(args), - &block) - end + ProcessDefinition.make_expression( + @context, + OpenWFE::to_expression_name(m), + ProcessDefinition.pack_args(args), + &block) + end - def self.method_missing (m, *args, &block) + def self.method_missing (m, *args, &block) - @ccontext = Context.new \ - if (not @ccontext) or @ccontext.discarded? + @ccontext = Context.new \ + if (not @ccontext) or @ccontext.discarded? - ProcessDefinition.make_expression( - @ccontext, - OpenWFE::to_expression_name(m), - ProcessDefinition.pack_args(args), - &block) - end + ProcessDefinition.make_expression( + @ccontext, + OpenWFE::to_expression_name(m), + ProcessDefinition.pack_args(args), + &block) + end - # - # builds an actual expression representation (a node in the - # process definition tree). - # - def self.make_expression (context, exp_name, params, &block) + # + # builds an actual expression representation (a node in the + # process definition tree). + # + def self.make_expression (context, exp_name, params, &block) - string_child = nil - #attributes = OpenWFE::SymbolHash.new - attributes = Hash.new + string_child = nil + #attributes = OpenWFE::SymbolHash.new + attributes = Hash.new - #puts " ... params.class is #{params.class}" + #puts " ... params.class is #{params.class}" - if params.kind_of?(Hash) + if params.kind_of?(Hash) - params.each do |k, v| + params.each do |k, v| - if k == '0' - string_child = v.to_s - else - #attributes[OpenWFE::symbol_to_name(k.to_s)] = v.to_s - attributes[OpenWFE::symbol_to_name(k.to_s)] = v - end - end + if k == '0' + string_child = v.to_s + else + #attributes[OpenWFE::symbol_to_name(k.to_s)] = v.to_s + attributes[OpenWFE::symbol_to_name(k.to_s)] = v + end + end - elsif params + elsif params - string_child = params.to_s - end + string_child = params.to_s + end - exp = [ exp_name, attributes, [] ] + exp = [ exp_name, attributes, [] ] - exp.last << string_child \ - if string_child + exp.last << string_child \ + if string_child - if context.parent_expression - # - # adding this new expression to its parent - # - context.parent_expression.last << exp - else - # - # an orphan, a top expression - # - context.top_expressions << exp - end + if context.parent_expression + # + # adding this new expression to its parent + # + context.parent_expression.last << exp + else + # + # an orphan, a top expression + # + context.top_expressions << exp + end - return exp unless block + return exp unless block - context.push_parent_expression exp + context.push_parent_expression exp - result = block.call + result = block.call - exp.last << result \ - if result and result.kind_of?(String) + exp.last << result \ + if result and result.kind_of?(String) - context.pop_parent_expression + context.pop_parent_expression - exp - end + exp + end - def do_make + def do_make - ProcessDefinition.do_make self - end + ProcessDefinition.do_make self + end - # - # A class method for actually "making" the process - # segment raw representation - # - def self.do_make (instance=nil) + # + # A class method for actually "making" the process + # segment raw representation + # + def self.do_make (instance=nil) - context = if @ccontext + context = if @ccontext - @ccontext.discard - # preventing further additions in case of reevaluation - @ccontext + @ccontext.discard + # preventing further additions in case of reevaluation + @ccontext - elsif instance + elsif instance - instance.make - instance.context - else + instance.make + instance.context + else - pdef = self.new - pdef.make - pdef.context - end + pdef = self.new + pdef.make + pdef.context + end - return context.top_expression if context.top_expression + return context.top_expression if context.top_expression - name, revision = - extract_name_and_revision(self.metaclass.to_s[8..-2]) + name, revision = + extract_name_and_revision(self.metaclass.to_s[8..-2]) - top_expression = [ - "process-definition", - { "name" => name, "revision" => revision }, - context.top_expressions - ] + top_expression = [ + "process-definition", + { "name" => name, "revision" => revision }, + context.top_expressions + ] - top_expression - end + top_expression + end - # - # Parses the string to find the class name of the process definition - # and returns that class (instance). - # - def self.extract_class (ruby_proc_def_string) + # + # Parses the string to find the class name of the process definition + # and returns that class (instance). + # + def self.extract_class (ruby_proc_def_string) - ruby_proc_def_string.each_line do |l| + ruby_proc_def_string.each_line do |l| - m = ClassNameRex.match l + m = ClassNameRex.match l - return eval(m[1]) if m - end + return eval(m[1]) if m + end - nil - end + nil + end + # + # Turns a String containing a ProcessDefinition ... + # + def self.eval_ruby_process_definition (code) + + #TreeChecker.check code # - # Turns a String containing a ProcessDefinition ... - # - def self.eval_ruby_process_definition (code, safety_level=2) + # checks for 'illicit' ruby code before the eval + # (now done in the DefParser) - # TODO : insert tree check + code, is_wrapped = wrap_code code - #puts "\nin:\n#{code}\n" + o = eval code, binding() - code, is_wrapped = wrap_code code + o = extract_class(code) \ + if (o == nil) or o.is_a?(Array) + #if (o == nil) or o.is_a?(SimpleExpRepresentation) + # + # grab the first process definition class found + # in the given code - o = Rufus::eval_safely code, safety_level, binding() + result = o.do_make - o = extract_class(code) \ - if (o == nil) or o.is_a?(Array) - #if (o == nil) or o.is_a?(SimpleExpRepresentation) - # - # grab the first process definition class found - # in the given code + return result.last.first if is_wrapped - #return o.do_make \ - # if o.is_a?(ProcessDefinition) or o.is_a?(Class) - #o + result + end - result = o.do_make + protected - #return result.first_child if is_wrapped - return result.last.first if is_wrapped + ClassNameRex = Regexp.compile( + " *class *([a-zA-Z0-9]*) *< .*ProcessDefinition") + ProcessDefinitionRex = Regexp.compile( + "^class *[a-zA-Z0-9]* *< .*ProcessDefinition") + ProcessNameAndDefRex = Regexp.compile( + "([^0-9_]*)_*([0-9].*)$") + ProcessNameRex = Regexp.compile( + "(.*$)") + EndsInDefinitionRex = Regexp.compile( + ".*Definition$") - result - end + def self.wrap_code (code) - protected + return [ code, false ] if ProcessDefinitionRex.match(code) - ClassNameRex = Regexp.compile( - " *class *([a-zA-Z0-9]*) *< .*ProcessDefinition") - ProcessDefinitionRex = Regexp.compile( - "^class *[a-zA-Z0-9]* *< .*ProcessDefinition") - ProcessNameAndDefRex = Regexp.compile( - "([^0-9_]*)_*([0-9].*)$") - ProcessNameRex = Regexp.compile( - "(.*$)") - EndsInDefinitionRex = Regexp.compile( - ".*Definition$") + s = "class NoName0 < ProcessDefinition" + s << "\n" + s << code + s << "\nend" - def self.wrap_code (code) + [ s, true ] + end - return [ code, false ] if ProcessDefinitionRex.match(code) + def self.pack_args (args) - s = "class NoName0 < ProcessDefinition" - s << "\n" - s << code - s << "\nend" + return args[0] if args.length == 1 - [ s, true ] - end + a = {} + args.each_with_index do |arg, index| + if arg.is_a?(Hash) + a = a.merge(arg) + break + end + a[index.to_s] = arg + end + a + end - def self.pack_args (args) + def self.extract_name_and_revision (s) - return args[0] if args.length == 1 + i = s.rindex("::") + s = s[i+2..-1] if i - a = {} - args.each_with_index do |arg, index| - if arg.is_a?(Hash) - a = a.merge(arg) - break - end - a[index.to_s] = arg - end - a - end + m = ProcessNameAndDefRex.match s + return [ as_name(m[1]), as_revision(m[2]) ] if m - def self.extract_name_and_revision (s) + m = ProcessNameRex.match s + return [ as_name(m[1]), '0' ] if m - i = s.rindex("::") - s = s[i+2..-1] if i + [ as_name(s), '0' ] + end - m = ProcessNameAndDefRex.match s - return [ as_name(m[1]), as_revision(m[2]) ] if m + def self.as_name (s) - m = ProcessNameRex.match s - return [ as_name(m[1]), '0' ] if m + return s[0..-11] if EndsInDefinitionRex.match(s) + s + end - [ as_name(s), '0' ] - end + def self.as_revision (s) - def self.as_name (s) + s.gsub("_", ".") + end - return s[0..-11] if EndsInDefinitionRex.match(s) - s - end + class Context - def self.as_revision (s) + attr_accessor :parent_expression, :top_expressions + attr_reader :previous_parent_expressions - s.gsub("_", ".") - end + def initialize + @parent_expression = nil + @top_expressions = [] + @previous_parent_expressions = [] + end - class Context + def discard + @discarded = true + end + def discarded? + (@discarded == true) + end - attr_accessor :parent_expression, :top_expressions - attr_reader :previous_parent_expressions + # + # puts the current parent expression on top of the 'previous + # parent expressions' stack, the current parent expression + # is replaced with the supplied parent expression. + # + def push_parent_expression (exp) - def initialize - @parent_expression = nil - @top_expressions = [] - @previous_parent_expressions = [] - end + @previous_parent_expressions.push(@parent_expression) \ + if @parent_expression - def discard - @discarded = true - end - def discarded? - (@discarded == true) - end + @parent_expression = exp + end - # - # puts the current parent expression on top of the 'previous - # parent expressions' stack, the current parent expression - # is replaced with the supplied parent expression. - # - def push_parent_expression (exp) + # + # Replaces the current parent expression with the one found + # on the top of the previous parent expression stack (pop). + # + def pop_parent_expression - @previous_parent_expressions.push(@parent_expression) \ - if @parent_expression + @parent_expression = @previous_parent_expressions.pop + end - @parent_expression = exp - end + # + # This method returns the top expression among the + # top expressions... + # + def top_expression - # - # Replaces the current parent expression with the one found - # on the top of the previous parent expression stack (pop). - # - def pop_parent_expression + return nil if @top_expressions.size > 1 - @parent_expression = @previous_parent_expressions.pop - end + exp = @top_expressions.first - # - # This method returns the top expression among the - # top expressions... - # - def top_expression - - return nil if @top_expressions.size > 1 - - exp = @top_expressions.first - - return exp if exp.first == "process-definition" - nil - end - end - end + return exp if exp.first == "process-definition" + nil + end + end + end end