rinterceptor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+