rinterceptor 0.1.0

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/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ Changes in version 0.1.0 (2009-03-9)
2
+ -------------------------------------
3
+ initial release
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ PKG_NAME = "rinterceptor"
4
+ PKG_VERSION = "0.1.0"
5
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
6
+ PKG_FILES = FileList[
7
+ '[A-Z]*',
8
+ 'lib/**/*'
9
+ ]
10
+ spec = Gem::Specification.new do |s|
11
+ s.platform = Gem::Platform::RUBY
12
+ s.summary = "it is a inheritable, reusable AOP framework"
13
+ s.name = PKG_NAME
14
+ s.version = PKG_VERSION
15
+ s.require_path = 'lib'
16
+ s.homepage = %q{http://rinter.rubyforge.org/}
17
+ s.rubyforge_project = 'Rinterceptor'
18
+ s.has_rdoc = false
19
+ s.authors = ["Leon Li"]
20
+ s.email = "scorpio_leon@hotmail.com"
21
+ s.files = PKG_FILES
22
+ s.description = <<-EOF
23
+ it is a inheritable, reusable AOP framework with regex rule support, let your interceptor simple, flexible and with high expandability
24
+ EOF
25
+ end
26
+ Rake::GemPackageTask.new(spec) do |pkg|
27
+ pkg.need_zip = true
28
+ pkg.need_tar = true
29
+ end
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rinterceptor'
3
+ module ExampleRinterceptor
4
+ def rinter_before(method, *args)
5
+ p "instance before -- method: #{method}, args: #{args} in ExampleRinterceptor"
6
+ end
7
+ def rinter_after(method, result, e, *args)
8
+ p "instance after -- method: #{method}, result: #{result}, e: #{e}, args: #{args} in ExampleRinterceptor"
9
+ result
10
+ end
11
+
12
+ module ClassMethods
13
+ def rinter_before(method, *args)
14
+ p "singleton before -- method: #{method}, args: #{args} in ExampleRinterceptor"
15
+ end
16
+ def rinter_after(method, result, e, *args)
17
+ p "singleton after -- method: #{method}, result: #{result}, e: #{e}, args: #{args} in ExampleRinterceptor"
18
+ end
19
+ end
20
+ include Rinterceptor
21
+ end
22
+
23
+ module SubExampleRinterceptor
24
+ def self.rinter_before_include_class(base)
25
+ p "before_include_class in SubExampleRinterceptor"
26
+ #set interceptor rules of instance methods, the variable can also be defined in class before include this module
27
+ base.instance_variable_set(:@include_i_methods, {nil => [/^i2_/, /^i3_/], :handler_it => /^i1_/})
28
+ end
29
+ def self.rinter_after_include_class(base)
30
+ p "after_include_class in SubExampleRinterceptor"
31
+ end
32
+ def rinter_handler_it_around(invocation)
33
+ p "instance handler_it around begin -- method: #{invocation.method}, args: #{invocation.args} in SubExampleRinterceptor"
34
+ result = invocation.invoke("inter", "ddddd")
35
+ p "instance handler_it around end -- method: #{invocation.method}, args: #{invocation.args} in SubExampleRinterceptor"
36
+ result
37
+ end
38
+ module ClassMethods
39
+ def rinter_before(method, *args)
40
+ p "singleton before -- method: #{method}, args: #{args} in SubExampleRinterceptor"
41
+ end
42
+ end
43
+ include ExampleRinterceptor
44
+ end
45
+
46
+
47
+
48
+ if __FILE__ == $0
49
+
50
+ class TestRinterceptor
51
+ def i1_test(x, y)
52
+ p "i1_test x:#{x} y:#{y}"
53
+ end
54
+ def i2_test(x, y)
55
+ p "i2_test x:#{x} y:#{y}"
56
+ end
57
+ def i3_test(x, y)
58
+ p "i3_test x:#{x} y:#{y}"
59
+ end
60
+ def self.s_test(x, y)
61
+ p "s_test x:#{x} y:#{y}"
62
+ end
63
+ #set interceptor rules of singleton methods, an alternative way is demonstrated in "self.rinter_before_include_class" of SubExampleRinterceptor
64
+ #@include_s_methods value example:
65
+ #String(for exactly match)
66
+ #Regexp
67
+ #[Regexp]
68
+ #{} (unless key.nil? use rinter_#{key}_around to handle it, otherwise same behavior as before)
69
+ #refor to SubExampleRinterceptor
70
+ @include_s_methods = [/^s_/]
71
+ include SubExampleRinterceptor
72
+ end
73
+
74
+ TestRinterceptor.new.i1_test("xxx", "yyy")
75
+ TestRinterceptor.new.i2_test("xxx", "yyy")
76
+ TestRinterceptor.new.i3_test("xxx", "yyy")
77
+ TestRinterceptor.s_test("xxx", "yyy")
78
+ end
79
+
80
+
@@ -0,0 +1,178 @@
1
+ =begin
2
+
3
+ For expandability, Class can not include me directly, only accept Module to include me
4
+ for example:
5
+
6
+ module MyRinterceptor
7
+ def instance_method
8
+ end
9
+ module ClassMethods #don't change this name if you need singleton method
10
+ def singleton_method
11
+ end
12
+ end
13
+ include Rinterceptor #should be placed at last line of this module
14
+ end
15
+
16
+ class YourClass
17
+ include MyRinterceptor
18
+ end
19
+
20
+
21
+ #you can refer to example_rinterceptor.rb
22
+ =end
23
+ #TODO nested interceptor
24
+ module Rinterceptor
25
+ def self.included(base)
26
+ raise 'Class can not include me directly, only accept Module to include me' if base.is_a?(Class)
27
+ base.extend(ClassMethods)
28
+ end
29
+
30
+ #overridable
31
+ def rinter_skip?
32
+ false
33
+ end
34
+
35
+ #overridable
36
+ def rinter_before(method, *args)
37
+ end
38
+
39
+ #overridable
40
+ def rinter_after(method, result, e, *args)
41
+ raise e unless e.nil?
42
+ result
43
+ end
44
+
45
+ #overridable
46
+ def rinter_around(invocation)
47
+ invocation.invoke
48
+ end
49
+
50
+ module ClassMethods
51
+ #for sub module
52
+ def included(base)
53
+ if base.is_a?(Class)
54
+ rinter_before_include_class(base) #only available in last module for preparing data of Class which will include it
55
+ base.extend(ClassMethods)
56
+ base.ancestors[1..-1].reverse.each {|p| base.extend(p::ClassMethods) if p.respond_to?(:rinter_here?)}
57
+ include_s_methods = base.include_s_methods || []
58
+ include_i_methods = base.include_i_methods || []
59
+ include_s_methods = RinterceptorUtil.process_include_methods(include_s_methods)
60
+ include_i_methods = RinterceptorUtil.process_include_methods(include_i_methods)
61
+ exclude_s_methods = (base.exclude_s_methods || []) + [/^rinter_/, /include_[is]_methods/, /exclude_[is]_methods/]
62
+ exclude_i_methods = (base.exclude_i_methods || []) + [/^rinter_/, /include_[is]_methods/, /exclude_[is]_methods/]
63
+ s_methods = (base.private_methods + base.singleton_methods).delete_if{|m| ! RinterceptorUtil.match_method?(m, include_s_methods, exclude_s_methods) }
64
+ i_methods = (base.private_instance_methods + base.instance_methods).delete_if{|m| ! RinterceptorUtil.match_method?(m, include_i_methods, exclude_i_methods) }
65
+ s_methods.each{|m| rinter_generate_proxy(base, m, include_s_methods.is_a?(Hash) ? include_s_methods : nil, true)}
66
+ i_methods.each{|m| rinter_generate_proxy(base, m, include_i_methods.is_a?(Hash) ? include_i_methods : nil)}
67
+ rinter_after_include_class(base) #only available in last module for preparing data of Class which will include it
68
+ else
69
+ base.extend(ClassMethods)
70
+ end
71
+ end
72
+ def rinter_here?
73
+ true
74
+ end
75
+
76
+ #overridable only in last module
77
+ def rinter_before_include_class(base)
78
+ end
79
+
80
+ #overridable only in last module
81
+ def rinter_after_include_class(base)
82
+ end
83
+
84
+ def rinter_generate_proxy(obj, method, methods, singleton=false)
85
+ handler = nil
86
+ unless methods.nil?
87
+ methods.each{|k, v| v.each{|vv| if method =~ vv then handler = method; break end }; unless handler.nil? then handler = k.nil? ? nil : "#{k}_"; break end}
88
+ end
89
+ obj.class_eval %{
90
+ #{"class << self" if singleton}
91
+ alias_method :old4rinter_#{method}, :#{method} unless method_defined?(:old4rinter_#{method})
92
+ def #{method}(*args)
93
+ return old4rinter_#{method}(*args) if rinter_skip?
94
+ rinter_before("#{method}", *args)
95
+ result = nil
96
+ e = nil
97
+ invocation = RinterceptorInvocation.new(self, "#{method}", *args)
98
+ begin
99
+ result = rinter_#{handler}around(invocation)
100
+ rescue => e
101
+ end
102
+ rinter_after("#{method}", result, e, *args)
103
+ result
104
+ end
105
+ #{"end" if singleton}
106
+ }
107
+ end
108
+
109
+ #target class' methods
110
+ attr_accessor :include_i_methods
111
+ attr_accessor :include_s_methods
112
+ attr_accessor :exclude_i_methods
113
+ attr_accessor :exclude_s_methods
114
+
115
+ #overridable
116
+ def rinter_skip?
117
+ false
118
+ end
119
+
120
+ #overridable
121
+ def rinter_before(method, *args)
122
+ end
123
+
124
+ #overridable
125
+ def rinter_after(method, result, e, *args)
126
+ raise e unless e.nil?
127
+ result
128
+ end
129
+
130
+ #overridable
131
+ def rinter_around(invocation)
132
+ invocation.invoke
133
+ end
134
+ end
135
+ end
136
+
137
+ module RinterceptorUtil
138
+ def self.match_method?(method, includes, excludes)
139
+ excludes.each {|i| return false if method =~ i}
140
+ real_includes = includes.is_a?(Array) ? includes : []
141
+ if includes.is_a?(Hash)
142
+ includes.each{|k, v| real_includes += v}
143
+ end
144
+ real_includes.each {|i| return true if method =~ i}
145
+ false
146
+ end
147
+ def self.process_include_methods(methods)
148
+ if methods.is_a?(Hash)
149
+ methods.each do |k, v|
150
+ if v.is_a?(String) || v.is_a?(Symbol)
151
+ v = Regexp.new("^#{v}$")
152
+ elsif v.is_a?(Array)
153
+ v.each_index{|i| v[i] = Regexp.new("^#{v[i]}$") if v[i].is_a?(String) || v[i].is_a?(Symbol)}
154
+ end
155
+ v = [v] if v.is_a?(Regexp)
156
+ methods[k] = v
157
+ end
158
+ end
159
+ methods
160
+ end
161
+ end
162
+
163
+ class RinterceptorInvocation
164
+ attr_accessor :object, :method, :args, :options
165
+ def initialize(object, method, *args)
166
+ @object = object
167
+ @method = method
168
+ @args = args
169
+ @options = {}
170
+ end
171
+ def invoke(*args)
172
+ unless @options.nil? || @options.empty?
173
+ @args = @args + [@options]
174
+ @options = nil
175
+ end
176
+ @object.send("old4rinter_#{@method}".to_sym, *(args.empty? ? @args : args))
177
+ end
178
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rinterceptor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Leon Li
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-09 00:00:00 +08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: it is a inheritable, reusable AOP framework with regex rule support, let your interceptor simple, flexible and with high expandability
17
+ email: scorpio_leon@hotmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - MIT-LICENSE
26
+ - Rakefile
27
+ - CHANGELOG
28
+ - lib/rinterceptor.rb
29
+ - lib/example_rinterceptor.rb
30
+ has_rdoc: false
31
+ homepage: http://rinter.rubyforge.org/
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project: Rinterceptor
52
+ rubygems_version: 1.3.1
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: it is a inheritable, reusable AOP framework
56
+ test_files: []
57
+