rsence 2.0.0.6.pre → 2.0.0.7.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,45 +7,69 @@
7
7
  ##
8
8
 
9
9
  module ::RSence
10
- module Plugins
11
- ## Interface to enable plugins in a plugin. Just include this in your subclass of Plugin.
12
- module PluginPlugins
13
- def init
14
- super
15
- @plugin_plugins = RSence::PluginManager.new( [ bundle_path('plugins') ] )
10
+ module Plugins
11
+
12
+ # Interface to enable plugins under a plugin.
13
+ # Just include this in your subclass of Plugin.
14
+ # The plugins loaded using this system are isolated from other plugins.
15
+ # To address them from this plugin, use @plugin_plugins instead of
16
+ # @plugins to address them.
17
+ module PluginPlugins
18
+
19
+ # Extended init, delegates calls to the sub-plugins.
20
+ def init
21
+ super
22
+ @plugin_plugins = RSence::PluginManager.new( [ bundle_path('plugins') ] )
23
+ end
24
+
25
+ # Extended open, delegates calls to the sub-plugins.
26
+ def open
27
+ super
28
+ @plugin_plugins.delegate(:open)
29
+ end
30
+
31
+ # Extended close, delegates calls to the sub-plugins.
32
+ def close
33
+ super
34
+ @plugin_plugins.delegate(:close)
35
+ end
36
+
37
+ # Extended flush, delegates calls to the sub-plugins.
38
+ def flush
39
+ super
40
+ @plugin_plugins.delegate(:flush)
41
+ end
42
+
43
+ # Extended idle, delegates calls to the sub-plugins.
44
+ def idle( msg )
45
+ super
46
+ @plugin_plugins.delegate(:idle,msg)
47
+ end
48
+
49
+ # Extended init_ses, delegates calls to the sub-plugins.
50
+ def init_ses( msg )
51
+ super
52
+ @plugin_plugins.delegate(:init_ses,msg)
53
+ end
54
+
55
+ # Extended restore_ses, delegates calls to the sub-plugins.
56
+ def restore_ses( msg )
57
+ super
58
+ @plugin_plugins.delegate(:restore_ses,msg)
59
+ end
60
+
61
+ # Extended cloned_target, delegates calls to the sub-plugins.
62
+ def cloned_target( msg, source_session )
63
+ super
64
+ @plugin_plugins.delegate(:cloned_target,msg,source_session)
65
+ end
66
+
67
+ # Extended cloned_source, delegates calls to the sub-plugins.
68
+ def cloned_source( msg, target_session )
69
+ super
70
+ @plugin_plugins.delegate(:cloned_source,msg,target_session)
71
+ end
72
+
73
+ end
16
74
  end
17
- def open
18
- super
19
- @plugin_plugins.delegate(:open)
20
- end
21
- def close
22
- super
23
- @plugin_plugins.delegate(:close)
24
- end
25
- def flush
26
- super
27
- @plugin_plugins.delegate(:flush)
28
- end
29
- def idle( msg )
30
- super
31
- @plugin_plugins.delegate(:idle,msg)
32
- end
33
- def init_ses( msg )
34
- super
35
- @plugin_plugins.delegate(:init_ses,msg)
36
- end
37
- def restore_ses( msg )
38
- super
39
- @plugin_plugins.delegate(:restore_ses,msg)
40
- end
41
- def cloned_target( msg, source_session )
42
- super
43
- @plugin_plugins.delegate(:cloned_target,msg,source_session)
44
- end
45
- def cloned_source( msg, target_session )
46
- super
47
- @plugin_plugins.delegate(:cloned_source,msg,target_session)
48
- end
49
- end
50
- end
51
75
  end
@@ -7,70 +7,70 @@
7
7
  ##
8
8
 
9
9
  module ::RSence
10
- module Plugins
11
- # Include this module in your plugin class to automatically
12
- # create and connect/disconnect an sqllite database.
13
- # The plugin instance will have a @db Sequel object refering
14
- # to the sqlite database automatically created
15
- module PluginSqliteDB
16
-
17
- # First calls superclass, then creates database directory and database.
18
- # Then calls init_db_tables.
19
- def init
20
- super
21
- db_dir = File.join( @path, 'db' )
22
- unless File.directory?( db_dir )
23
- Dir.mkdir( db_dir )
24
- end
25
- @db_path = File.join( db_dir, "#{@name}.db" )
26
- unless File.exist?( @db_path )
27
- @db = Sequel.sqlite( @db_path )
28
- create_db_tables
29
- @db.disconnect
10
+ module Plugins
11
+ # Include this module in your plugin class to automatically
12
+ # create and connect/disconnect an sqlite database.
13
+ # The plugin instance will have a @db Sequel object referring
14
+ # to the sqlite database automatically created
15
+ module PluginSqliteDB
16
+
17
+ # First calls superclass, then creates database directory and database.
18
+ # Then calls init_db_tables.
19
+ def init
20
+ super
21
+ db_dir = File.join( @path, 'db' )
22
+ unless File.directory?( db_dir )
23
+ Dir.mkdir( db_dir )
24
+ end
25
+ @db_path = File.join( db_dir, "#{@name}.db" )
26
+ unless File.exist?( @db_path )
27
+ @db = Sequel.sqlite( @db_path )
28
+ create_db_tables
29
+ @db.disconnect
30
+ end
31
+ end
32
+
33
+ # Automatically opens the database connection, then calls update_db.
34
+ def open
35
+ @db = Sequel.sqlite( @db_path )
36
+ update_db
37
+ super
38
+ end
39
+
40
+ # Automatically closes (disconnects) the database. Calls flush_db before closing.
41
+ def close
42
+ flush_db
43
+ @db.disconnect
44
+ super
45
+ end
46
+
47
+ # Extend this method to do something immediately after the @db object is assigned.
48
+ # An usage scenario would be updating some tables or deleting some junk rows.
49
+ def update_db
50
+ end
51
+
52
+ # Extend this method to do something immediately before the @db object is disconnected.
53
+ # An usage scenario would be deleting some junk rows or writing some pending data in memory into the database.
54
+ def flush_db
55
+ end
56
+
57
+ # Extend this method to define tables or initial data for the tables.
58
+ # It's called once, when the database is created.
59
+ #
60
+ # NOTE: In a future reversion, tables might be defined from a configuration file.
61
+ #
62
+ # = Usage:
63
+ # @db.create_table :my_table do
64
+ # primary_key :id
65
+ # String :my_text_column
66
+ # end
67
+ # my_table = @db[:my_table]
68
+ # my_table.insert(:my_text_column => 'Some text')
69
+ #
70
+ def create_db_tables
71
+ end
72
+
30
73
  end
31
74
 
32
75
  end
33
-
34
- # Automatically opens the database connection, then calls update_db.
35
- def open
36
- @db = Sequel.sqlite( @db_path )
37
- update_db
38
- super
39
- end
40
-
41
- # Automatically closes (disconnects) the database. Calls flush_db before closing.
42
- def close
43
- flush_db
44
- @db.disconnect
45
- super
46
- end
47
-
48
- # Extend this method to do something immediately after the @db object is assigned.
49
- # An usage scenario would be updating some tables or deleting some junk rows.
50
- def update_db
51
- end
52
-
53
- # Extend this method to do something immediately before the @db object is disconnected.
54
- # An usage scenario would be deleting some junk rows or writing some pending data in memory into the database.
55
- def flush_db
56
- end
57
-
58
- # Extend this method to define tables or initial data for the tables.
59
- # It's called once, when the database is created.
60
- #
61
- # NOTE: In a future reversion, tables might be defined from a configuration file.
62
- #
63
- # = Usage:
64
- # @db.create_table :my_table do
65
- # primary_key :id
66
- # String :my_text_column
67
- # end
68
- # my_table = @db[:my_table]
69
- # my_table.insert(:my_text_column => 'Some text')
70
- #
71
- def create_db_tables
72
- end
73
- end
74
-
75
- end
76
76
  end
@@ -7,110 +7,101 @@
7
7
  ##
8
8
 
9
9
  module ::RSence
10
- module Plugins
11
- module PluginUtil
12
-
13
- include RSence
14
-
15
- #
16
- # def self.method_missing( name, *args, &block )
17
- # puts "method_missing:"
18
- # puts " name: #{name.inspect}"
19
- # puts " args: #{args.inspect}"
20
- # puts " block: #{block.inspect}"
21
- # if name == :bundle_path
22
- # return Info.new( Module.nesting ).bundle_path
23
- # end
24
- # end
25
-
26
- # Extend to do any initial configuration. Not doing anything by default.
27
- def init
28
- end
29
-
30
- # Extend this method to open objects like streams and database connections.
31
- # It is called when everything is constructed after all plugins are loaded.
32
- def open
33
- end
34
-
35
- # Extend to save your plugin state or store any data that needs to be
36
- # persistent. It's always called before close, but doesn't necessarily mean
37
- # a close call is imminent.
38
- def flush
39
- end
40
-
41
- # Extend this method to close objects like streams and database connections.
42
- # It's called when plugins are about to be destructed, so don't expect any
43
- # calls after it has been called. When this method is called, it's the last
44
- # chance to save persistent data before being destructed, so implement
45
- # the +#flush+ method for primarily storing data.
46
- def close
47
- end
48
-
49
- # Returns the contents of the file given as +path+.
50
- #
51
- # The plugin bundle's path is used as the prefix, unless +path+ starts with '/' or '..'
52
- #
53
- # If the file doesn't exist, it returns +false+.
54
- def file_read( path )
55
- path = bundle_path( path )
56
- return false unless File.exist?( path )
57
- return File.read( path )
58
- end
59
-
60
- def yaml_read( path )
61
- file_data = file_read( path )
62
- if not file_data
63
- return false
64
- else
65
- return YAML.load( file_data )
10
+ module Plugins
11
+
12
+ # This module contains common functionality for both the Plugin and
13
+ # the Servlet base classes.
14
+ module PluginUtil
15
+
16
+ include RSence
17
+
18
+ # Extend to do any initial configuration. Not doing anything by default.
19
+ def init
20
+ end
21
+
22
+ # Extend this method to open objects like streams and database connections.
23
+ # It is called when everything is constructed after all plugins are loaded.
24
+ def open
25
+ end
26
+
27
+ # Extend to save your plugin state or store any data that needs to be
28
+ # persistent. It's always called before close, but doesn't necessarily mean
29
+ # a close call is imminent.
30
+ def flush
31
+ end
32
+
33
+ # Extend this method to close objects like streams and database connections.
34
+ # It's called when plugins are about to be destructed, so don't expect any
35
+ # calls after it has been called. When this method is called, it's the last
36
+ # chance to save persistent data before being destructed, so implement
37
+ # the +#flush+ method for primarily storing data.
38
+ def close
39
+ end
40
+
41
+ # Returns the contents of the file given as +path+.
42
+ #
43
+ # The plugin bundle's path is used as the prefix, unless +path+ starts with '/' or '..'
44
+ #
45
+ # If the file doesn't exist, it returns +false+.
46
+ def file_read( path )
47
+ path = bundle_path( path )
48
+ return false unless File.exist?( path )
49
+ return File.read( path )
50
+ end
51
+
52
+ def yaml_read( path )
53
+ file_data = file_read( path )
54
+ if not file_data
55
+ return false
56
+ else
57
+ return YAML.load( file_data )
58
+ end
59
+ end
60
+
61
+ # Writes the +data+ into the file +path+.
62
+ #
63
+ # The plugin bundle's path is used as the prefix, unless +path+ starts with '/' or '..'
64
+ #
65
+ # It returns a success code (+false+ for failure and +true+ for success).
66
+ def file_write( path, data )
67
+ path = bundle_path( path )
68
+ begin
69
+ datafile = File.open( path, 'wb' )
70
+ datafile.write( data )
71
+ datafile.close
72
+ return true
73
+ rescue => e
74
+ warn "file_write error for path #{path} #{e}"
75
+ return false
76
+ end
77
+ end
78
+ alias file_save file_write
79
+
80
+ # Makes a full path using the plugin bundle as the 'local path'.
81
+ # The (optional) +prefix+ is a subdirectory in the bundle,
82
+ # the +suffix+ is the file extension.
83
+ def bundle_path( path, prefix=false, suffix=false )
84
+ if suffix
85
+ path = "#{path}#{suffix}" unless path.end_with?(suffix)
86
+ end
87
+ if prefix
88
+ path = File.join( prefix, path )
89
+ end
90
+ path = File.expand_path( path, @path )
91
+ return path
92
+ end
93
+
94
+ def compose_plugin_path( *args )
95
+ warn "'compose_plugin_path' is deprecated. Use 'bundle_path' instead."
96
+ bundle_path( *args )
97
+ end
98
+
99
+ # Helper method to return the time formatted according to the HTTP RFC
100
+ def httime(time=false)
101
+ time = Time.new unless time
102
+ return time.gmtime.strftime('%a, %d %b %Y %H:%M:%S %Z')
103
+ end
104
+
66
105
  end
67
106
  end
68
-
69
- def method_undefined?( *args )
70
- puts "Method undefined: #{args.inspect}"
71
- end
72
-
73
- # Writes the +data+ into the file +path+.
74
- #
75
- # The plugin bundle's path is used as the prefix, unless +path+ starts with '/' or '..'
76
- #
77
- # It returns a success code (+false+ for failure and +true+ for success).
78
- def file_write( path, data )
79
- path = bundle_path( path )
80
- begin
81
- datafile = File.open( path, 'wb' )
82
- datafile.write( data )
83
- datafile.close
84
- return true
85
- rescue => e
86
- warn "file_write error for path #{path} #{e}"
87
- return false
88
- end
89
- end
90
- alias file_save file_write
91
-
92
- # Makes a full path using the plugin bundle as the 'local path'.
93
- # The (optional) +prefix+ is a subdirectory in the bundle,
94
- # the +suffix+ is the file extension.
95
- def bundle_path( path, prefix=false, suffix=false )
96
- if suffix
97
- path = "#{path}#{suffix}" unless path.end_with?(suffix)
98
- end
99
- if prefix
100
- path = File.join( prefix, path )
101
- end
102
- path = File.expand_path( path, @path )
103
- return path
104
- end
105
-
106
- alias compose_plugin_path bundle_path
107
-
108
- # Helper method to return the time formatted according to the HTTP RFC
109
- def httime(time=false)
110
- time = Time.new unless time
111
- return time.gmtime.strftime('%a, %d %b %Y %H:%M:%S %Z')
112
- end
113
-
114
- end
115
- end
116
107
  end
@@ -5,166 +5,114 @@
5
5
  # You should have received a copy of the GNU General Public License along
6
6
  # with this software package. If not, contact licensing@riassence.com
7
7
  ##
8
- # if RUBY_VERSION.to_f >= 1.9
9
- # # with_module comes from:
10
- # # http://coderrr.wordpress.com/2009/05/18/dynamically-adding-a-constant-nesting-in-ruby-1-9/
11
- # module Kernel
12
- # def with_module(*consts, &blk)
13
- # slf = blk.binding.eval('self')
14
- # l = lambda { slf.instance_eval(&blk) }
15
- # consts.reverse.inject(l) {|l, k| lambda { k.class_eval(&l) } }.call
16
- # end
17
- # end
18
- # end
19
-
20
- # def bundle_loader( params )
21
- # src_path = params[:src_path]
22
- # mod = Module.new do |m|
23
- # @@bundle_path = params[:bundle_path ]
24
- # @@bundle_name = params[:bundle_name ]
25
- # @@bundle_info = params[:bundle_info ]
26
- # @@plugin_manager = params[:plugin_manager]
27
- # def m.bundle_path; @@bundle_path; end
28
- # def m.bundle_name; @@bundle_name; end
29
- # def m.bundle_info; @@bundle_info; end
30
- # def m.bundle_manager; @@bundle_manager; end
31
- # begin
32
- # # if RUBY_VERSION.to_f >= 1.9
33
- # # # with_module(m) do
34
- # # src = File.read(src_path)
35
- # # self.module_eval(
36
- # # <<-SRC
37
- # # puts %{--- bundle_path: #{bundle_path.inspect}}
38
- # # #{src}
39
- # # SRC
40
- # # )
41
- # # # end
42
- # # else
43
- # if params[:bundle_info][:inits_self] == false or RUBY_VERSION.to_f >= 1.9
44
- # m::module_eval( File.read(src_path) )
45
- # elsif params[:bundle_info][:reloadable] == false
46
- # require src_path[0..-4]
47
- # else
48
- # load src_path
49
- # end
50
- # # end
51
- # rescue => e
52
- # @@plugin_manager.plugin_error(
53
- # e,
54
- # 'BundleLoaderError',
55
- # "An error occurred while loading the plugin bundle #{@@bundle_name}.",
56
- # @@bundle_path
57
- # )
58
- # end
59
- # end
60
- # return mod
61
- # end
62
- #
63
-
64
- module RSence
65
-
66
8
  require 'plugins/plugins'
67
9
 
68
- ## = Abstract
69
- ## PluginManager is the service that loads and provides method delegation
70
- ## amongst all installed plugins.
71
- ##
72
- ## = Usage
73
- ## plugin_paths = [ 'plugins', '/home/me/rsence/plugins' ]
74
- ## myPluginManager = RSence::PluginManager.new( plugin_paths )
75
- ##
76
- class PluginManager
77
-
78
- attr_reader :transporter, :sessions
10
+ module RSence
79
11
 
80
- # Initialize with a list of directories as plugin_paths.
81
- # It's an array containing all plugin directories to scan.
82
- def initialize( plugin_paths, transporter=nil, autoreload=false )
83
- if transporter
84
- @transporter = transporter
85
- @sessions = transporter.sessions
86
- end
87
- @plugin_paths = plugin_paths
88
- puts "Loading plugins..." if RSence.args[:verbose]
89
- scan_plugins
90
- puts "Plugins loaded." if RSence.args[:verbose]
91
- if autoreload
92
- @thr = Thread.new do
93
- Thread.pass
94
- while true
95
- begin
96
- changed_plugins!
97
- rescue => e
98
- warn e.inspect
12
+ ## = Abstract
13
+ ## PluginManager is the service that loads and provides method delegation
14
+ ## amongst its plugin bundles.
15
+ ##
16
+ ## = Usage
17
+ ## plugin_paths = [ 'plugins', '/home/me/rsence/plugins' ]
18
+ ## myPluginManager = RSence::PluginManager.new( plugin_paths )
19
+ ##
20
+ class PluginManager
21
+
22
+ attr_reader :transporter, :sessions
23
+
24
+ # Initialize with a list of directories as plugin_paths.
25
+ # It's an array containing all plugin directories to scan.
26
+ def initialize( plugin_paths, transporter=nil, autoreload=false, name_prefix=false )
27
+ if transporter
28
+ @transporter = transporter
29
+ @sessions = transporter.sessions
30
+ end
31
+ @name_prefix = name_prefix
32
+ @plugin_paths = plugin_paths
33
+ puts "Loading #{name_prefix+' ' if name_prefix}plugins..." if RSence.args[:verbose]
34
+ scan_plugins
35
+ puts "Plugins #{name_prefix+' ' if name_prefix}loaded." if RSence.args[:verbose]
36
+ if autoreload
37
+ @thr = Thread.new do
38
+ Thread.pass
39
+ while true
40
+ begin
41
+ changed_plugins!
42
+ rescue => e
43
+ warn e.inspect
44
+ end
45
+ sleep 3
99
46
  end
100
- sleep 3
101
47
  end
102
48
  end
103
49
  end
104
- end
105
-
106
- def method_missing( sym, *args, &block )
107
- if @registry.has_key?(sym)
108
- if args == [] and block == nil
109
- return @registry[sym]
110
- elsif block == nil
111
- call( sym, *args )
50
+
51
+ # By default, calling a method not defined calls a plugin of that name
52
+ def method_missing( sym, *args, &block )
53
+ if @registry.has_key?(sym)
54
+ if args == [] and block == nil
55
+ return @registry[sym]
56
+ elsif block == nil
57
+ call( sym, *args )
58
+ end
112
59
  end
113
60
  end
114
- end
115
-
116
- def changed_plugins!
117
- @plugin_paths.each do |path|
118
- next unless File.directory? path
119
- Dir.entries(path).each do |bundle_name|
120
- next if bundle_name =~ /&\./
121
- bundle_path = File.expand_path( File.join( path, bundle_name ) )
122
- next unless File.directory?( bundle_path )
123
- bundle_file = bundle_name+'.rb'
124
- next unless File.exists?( File.join( bundle_path, bundle_file ) )
125
- if File.exists?( File.join( bundle_path, 'disabled' ) )
126
- if @registry.has_key?( bundle_name.to_sym )
127
- puts "Disabling bundle #{bundle_name}..."
128
- online_status = @transporter.online?
129
- @transporter.online = false
130
- unload_bundle( bundle_name.to_sym )
131
- @transporter.online = online_status
132
- if RSence.args[:say]
133
- Thread.new do
134
- Thread.pass
135
- system(%{say "Unloaded #{bundle_name.to_s}."})
136
- end
137
- end
138
- end
139
- else
140
- if not @registry.has_key?( bundle_name.to_sym )
141
- puts "Loading bundle #{bundle_name}..."
142
- online_status = @transporter.online?
143
- @transporter.online = false
144
- load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' )
145
- call( bundle_name.to_sym, :open )
146
- @transporter.online = online_status
147
- if RSence.args[:say]
148
- Thread.new do
149
- Thread.pass
150
- system(%{say "Loaded #{bundle_name.to_s}."})
61
+
62
+ # Checks for changed plugin bundles and unloads/loads/reloads them accordingly.
63
+ def changed_plugins!
64
+ @plugin_paths.each do |path|
65
+ next unless File.directory? path
66
+ Dir.entries(path).each do |bundle_name|
67
+ next if bundle_name =~ /&\./
68
+ bundle_path = File.expand_path( File.join( path, bundle_name ) )
69
+ next unless File.directory?( bundle_path )
70
+ bundle_file = bundle_name+'.rb'
71
+ next unless File.exists?( File.join( bundle_path, bundle_file ) )
72
+ if File.exists?( File.join( bundle_path, 'disabled' ) )
73
+ if @registry.has_key?( bundle_name.to_sym )
74
+ puts "Disabling bundle #{bundle_name}..."
75
+ online_status = @transporter.online?
76
+ @transporter.online = false
77
+ unload_bundle( bundle_name.to_sym )
78
+ @transporter.online = online_status
79
+ if RSence.args[:say]
80
+ Thread.new do
81
+ Thread.pass
82
+ system(%{say "Unloaded #{bundle_name.to_s}."})
83
+ end
151
84
  end
152
85
  end
153
86
  else
154
- # puts "Checking if bundle #{bundle_name} is changed..."
155
- info = @info[bundle_name.to_sym]
156
- if info[:reloadable] and plugin_changed?( bundle_name.to_sym )
157
- puts "Bundle #{bundle_name} has changed, reloading..."
87
+ if not @registry.has_key?( bundle_name.to_sym )
88
+ puts "Loading bundle #{bundle_name}..."
158
89
  online_status = @transporter.online?
159
90
  @transporter.online = false
160
- unload_bundle( bundle_name.to_sym )
161
91
  load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' )
162
92
  call( bundle_name.to_sym, :open )
163
93
  @transporter.online = online_status
164
94
  if RSence.args[:say]
165
95
  Thread.new do
166
96
  Thread.pass
167
- system(%{say "Reloaded #{bundle_name.to_s}."})
97
+ system(%{say "Loaded #{bundle_name.to_s}."})
98
+ end
99
+ end
100
+ else
101
+ # puts "Checking if bundle #{bundle_name} is changed..."
102
+ info = @info[bundle_name.to_sym]
103
+ if info[:reloadable] and plugin_changed?( bundle_name.to_sym )
104
+ puts "Bundle #{bundle_name} has changed, reloading..."
105
+ online_status = @transporter.online?
106
+ @transporter.online = false
107
+ unload_bundle( bundle_name.to_sym )
108
+ load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' )
109
+ call( bundle_name.to_sym, :open )
110
+ @transporter.online = online_status
111
+ if RSence.args[:say]
112
+ Thread.new do
113
+ Thread.pass
114
+ system(%{say "Reloaded #{bundle_name.to_s}."})
115
+ end
168
116
  end
169
117
  end
170
118
  end
@@ -172,340 +120,351 @@ class PluginManager
172
120
  end
173
121
  end
174
122
  end
175
- end
176
-
177
- def unload_bundle( bundle_name )
178
- puts "unloading bundle: #{bundle_name.inspect}" if RSence.args[:debug]
179
- if @registry.has_key?( bundle_name )
180
- call( bundle_name, :flush )
181
- call( bundle_name, :close )
182
- @registry.delete( bundle_name )
183
- @aliases.each do |a_name,b_name|
184
- if b_name == bundle_name
185
- @aliases.delete( a_name )
123
+
124
+ # Unloads the plugin bundle named +bundle_name+
125
+ def unload_bundle( bundle_name )
126
+ puts "unloading bundle: #{bundle_name.inspect}" if RSence.args[:debug]
127
+ if @registry.has_key?( bundle_name )
128
+ call( bundle_name, :flush )
129
+ call( bundle_name, :close )
130
+ @registry.delete( bundle_name )
131
+ @aliases.each do |a_name,b_name|
132
+ if b_name == bundle_name
133
+ @aliases.delete( a_name )
134
+ end
135
+ end
136
+ if @servlets.include?( bundle_name )
137
+ @servlets.delete( bundle_name )
138
+ end
139
+ if @info.include?( bundle_name )
140
+ @info.delete( bundle_name )
186
141
  end
187
- end
188
- if @servlets.include?( bundle_name )
189
- @servlets.delete( bundle_name )
190
- end
191
- if @info.include?( bundle_name )
192
- @info.delete( bundle_name )
193
142
  end
194
143
  end
195
- end
196
-
197
- def plugin_changed?( plugin_name )
198
- info = @info[plugin_name]
199
- last_changed = info[:last_changed]
200
- newest_change = most_recent( info[:path], last_changed )
201
- return last_changed < newest_change
202
- end
203
-
204
- # Top-level method for scanning all plugin directories.
205
- # Clears previously loaded plugins.
206
- def scan_plugins
207
- @registry = {}
208
- @info = {}
209
- @aliases = {}
210
- @servlets = []
211
- @plugin_paths.each do |path|
212
- next unless File.directory? path
213
- scan_plugindir( path )
144
+
145
+ # Returns true, if a plugin bundle has changed.
146
+ # Only compares timestamp, not checksum.
147
+ def plugin_changed?( plugin_name )
148
+ info = @info[plugin_name]
149
+ last_changed = info[:last_changed]
150
+ newest_change = most_recent( info[:path], last_changed )
151
+ return last_changed < newest_change
214
152
  end
215
- delegate( :open )
216
- end
217
153
 
218
- def registry( plugin_name )
219
- return @registry[ plugin_name ]
220
- end
221
- alias [] registry
222
-
223
- # Scans a directory of plugins, calls +load_plugin+ for bundles that match
224
- # the definition of a plugin bundle.
225
- # - Skips bundles starting with a dot
226
- # - Skips bundles without a ruby source file with the same
227
- # name as the directory (plus '.rb').
228
- # - Skips bundles containing a file or directory named 'disabled'
229
- def scan_plugindir( path )
230
- Dir.entries(path).each do |bundle_name|
231
- next if bundle_name[0].chr == '.'
232
- bundle_path = File.expand_path( File.join( path, bundle_name ) )
233
- next unless File.directory?( bundle_path )
234
- bundle_file = bundle_name+'.rb'
235
- if not File.exists?( File.join( bundle_path, bundle_file ) )
236
- bundle_file = 'main.rb'
237
- next unless File.exists?( File.join( bundle_path, bundle_file ) )
154
+ # Top-level method for scanning all plugin directories.
155
+ # Clears previously loaded plugins.
156
+ def scan_plugins
157
+ @registry = {}
158
+ @info = {}
159
+ @aliases = {}
160
+ @servlets = []
161
+ @plugin_paths.each do |path|
162
+ next unless File.directory? path
163
+ scan_plugindir( path )
238
164
  end
239
- next if File.exists?( File.join( bundle_path, 'disabled' ) )
165
+ delegate( :open )
166
+ end
167
+
168
+ # Returns the registry data for plugin bundle +plugin_name+
169
+ def registry( plugin_name )
170
+ return @registry[ plugin_name ]
171
+ end
172
+ alias [] registry
173
+
174
+ # Scans a directory of plugins, calls +load_plugin+ for bundles that match
175
+ # the definition of a plugin bundle.
176
+ # - Skips bundles starting with a dot
177
+ # - Skips bundles without a ruby source file with the same
178
+ # name as the directory (plus '.rb').
179
+ # - Skips bundles containing a file or directory named 'disabled'
180
+ def scan_plugindir( path )
181
+ Dir.entries(path).each do |bundle_name|
182
+ next if bundle_name[0].chr == '.'
183
+ bundle_path = File.expand_path( File.join( path, bundle_name ) )
184
+ next unless File.directory?( bundle_path )
185
+ bundle_file = bundle_name+'.rb'
186
+ if not File.exists?( File.join( bundle_path, bundle_file ) )
187
+ bundle_file = 'main.rb'
188
+ next unless File.exists?( File.join( bundle_path, bundle_file ) )
189
+ end
190
+ next if File.exists?( File.join( bundle_path, 'disabled' ) )
240
191
 
241
- load_bundle( bundle_path, bundle_name.to_sym, bundle_file )
192
+ load_bundle( bundle_path, bundle_name.to_sym, bundle_file )
193
+ end
242
194
  end
243
- end
244
195
 
245
- # Finds the most recent file in the path
246
- def most_recent( bundle_path, newest_date=0 )
247
- path_date = File.stat( bundle_path ).mtime.to_i
248
- is_dir = File.directory?( bundle_path )
249
- if path_date > newest_date and not is_dir
250
- # puts "File is newer: #{bundle_path}"
251
- newest_date = path_date
252
- end
253
- if is_dir
254
- Dir.entries( bundle_path ).each do |entry_name|
255
- next if entry_name[0].chr == '.'
256
- full_path = File.join( bundle_path, entry_name )
257
- unless File.directory?( full_path )
258
- next unless entry_name.include?('.') and ['yaml','rb'].include?( entry_name.split('.')[-1] )
196
+ # Finds the most recent file in the path
197
+ def most_recent( bundle_path, newest_date=0 )
198
+ path_date = File.stat( bundle_path ).mtime.to_i
199
+ is_dir = File.directory?( bundle_path )
200
+ if path_date > newest_date and not is_dir
201
+ # puts "File is newer: #{bundle_path}"
202
+ newest_date = path_date
203
+ end
204
+ if is_dir
205
+ Dir.entries( bundle_path ).each do |entry_name|
206
+ next if entry_name[0].chr == '.'
207
+ full_path = File.join( bundle_path, entry_name )
208
+ unless File.directory?( full_path )
209
+ next unless entry_name.include?('.') and ['yaml','rb'].include?( entry_name.split('.')[-1] )
210
+ end
211
+ newest_date = most_recent( full_path, newest_date )
259
212
  end
260
- newest_date = most_recent( full_path, newest_date )
261
213
  end
214
+ return newest_date
262
215
  end
263
- return newest_date
264
- end
265
216
 
266
- # Gets plugin information
267
- def bundle_info( bundle_path )
217
+ # Gets plugin information
218
+ def bundle_info( bundle_path )
268
219
 
269
- bundle_name = File.split( bundle_path )[1]
220
+ bundle_name = File.split( bundle_path )[1]
270
221
 
271
- # Default bundle information
272
- info = {
273
- # The human-readable product name of the package
274
- :title => bundle_name.capitalize,
222
+ # Default bundle information
223
+ info = {
224
+ # The human-readable product name of the package
225
+ :title => bundle_name.capitalize,
275
226
 
276
- # The human-readable version of the package
277
- :version => '0.0.0',
227
+ # The human-readable version of the package
228
+ :version => '0.0.0',
278
229
 
279
- # A brief description of the package (rdoc formatting supported)
280
- :description => 'No Description given',
230
+ # A brief description of the package (rdoc formatting supported)
231
+ :description => 'No Description given',
281
232
 
282
- # A flag (when false) prevents the plugin from automatically reload when changed.
283
- :reloadable => true,
233
+ # A flag (when false) prevents the plugin from automatically reload when changed.
234
+ :reloadable => true,
284
235
 
285
- # A flag (when false) enables automatic construction
286
- # of the Plugin and Servlet classes contained.
287
- :inits_self => false,
236
+ # A flag (when false) enables automatic construction
237
+ # of the Plugin and Servlet classes contained.
238
+ :inits_self => false,
288
239
 
289
- # System version requirement.
290
- :sys_version => '>= 1.0.0',
240
+ # System version requirement.
241
+ :sys_version => '>= 1.0.0',
291
242
 
292
- # Path to bundle
293
- :path => bundle_path,
243
+ # Path to bundle
244
+ :path => bundle_path,
294
245
 
295
- # Name of bundle
296
- :name => bundle_name.to_sym,
246
+ # Name of bundle
247
+ :name => bundle_name.to_sym,
297
248
 
298
- # Last change
299
- :last_changed => most_recent( bundle_path )
249
+ # Last change
250
+ :last_changed => most_recent( bundle_path )
300
251
 
301
- }
252
+ }
302
253
 
303
- info_path = File.join( bundle_path, 'info.yaml' )
304
- if File.exists?( info_path )
305
- info_yaml = YAML.load( File.read( info_path ) )
306
- info_yaml.each do |info_key,info_value|
307
- info[ info_key.to_sym ] = info_value
254
+ info_path = File.join( bundle_path, 'info.yaml' )
255
+ if File.exists?( info_path )
256
+ info_yaml = YAML.load( File.read( info_path ) )
257
+ info_yaml.each do |info_key,info_value|
258
+ info[ info_key.to_sym ] = info_value
259
+ end
308
260
  end
309
- end
310
- return info
261
+ return info
311
262
 
312
- end
313
-
314
- # Loads a plugin bundle.
315
- def load_bundle( bundle_path, bundle_name, bundle_file )
316
- puts "loading bundle: #{bundle_name.inspect}" if RSence.args[:debug]
317
- if @registry.has_key?( bundle_name.to_sym )
318
- warn "Warning: Bundle #{bundle_name} already loaded."
319
- return
320
263
  end
264
+
265
+ # Loads a plugin bundle.
266
+ def load_bundle( bundle_path, bundle_name, bundle_file )
267
+ puts "loading bundle: #{bundle_name.inspect}" if RSence.args[:debug]
268
+ if @registry.has_key?( bundle_name.to_sym )
269
+ warn "Warning: Bundle #{bundle_name} already loaded."
270
+ return
271
+ end
321
272
 
322
- bundle_file_path = File.join( bundle_path, bundle_file )
273
+ bundle_file_path = File.join( bundle_path, bundle_file )
323
274
 
324
- bundle_info = bundle_info( bundle_path )
275
+ bundle_info = bundle_info( bundle_path )
325
276
 
326
- @info[bundle_name.to_sym] = bundle_info
277
+ @info[bundle_name.to_sym] = bundle_info
327
278
 
328
- bundle_src = File.read( bundle_file_path )
279
+ bundle_src = File.read( bundle_file_path )
329
280
 
330
- module_ns = Plugins.bundle_loader( {
331
- :bundle_path => bundle_path,
332
- :bundle_name => bundle_name,
333
- :bundle_info => bundle_info,
334
- :plugin_manager => self,
335
- :src_path => bundle_file_path,
336
- :src => bundle_src
337
- } )
281
+ module_ns = Plugins.bundle_loader( {
282
+ :bundle_path => bundle_path,
283
+ :bundle_name => bundle_name,
284
+ :bundle_info => bundle_info,
285
+ :plugin_manager => self,
286
+ :src_path => bundle_file_path,
287
+ :src => bundle_src
288
+ } )
338
289
 
339
- if bundle_info[:inits_self]
340
- warn "Plugins can't init them self anymore. Please fix plugin: #{bundle_name.inspect}"
341
- else
342
- module_ns.constants.each do |module_const_name|
343
- module_const = module_ns.const_get( module_const_name )
344
- if module_const.class == Class
345
- bundle_type = module_const.bundle_type
346
- if [:Servlet, :Plugin, :GUIPlugin].include? bundle_type
347
- bundle_inst = module_const.new( bundle_name, bundle_info, bundle_path, self )
348
- bundle_inst.register( bundle_name ) if [ :Plugin, :GUIPlugin ].include?( bundle_type )
349
- break
290
+ if bundle_info[:inits_self]
291
+ warn "Plugins can't init them self anymore. Please fix plugin: #{bundle_name.inspect}"
292
+ else
293
+ module_ns.constants.each do |module_const_name|
294
+ module_const = module_ns.const_get( module_const_name )
295
+ if module_const.class == Class
296
+ bundle_type = module_const.bundle_type
297
+ if [:Servlet, :Plugin, :GUIPlugin].include? bundle_type
298
+ bundle_inst = module_const.new( bundle_name, bundle_info, bundle_path, self )
299
+ bundle_inst.register( bundle_name ) if [ :Plugin, :GUIPlugin ].include?( bundle_type )
300
+ break
301
+ else
302
+ warn "Can't init class: #{module_const.to_s}"
303
+ break
304
+ end
350
305
  else
351
- warn "Can't init class: #{module_const.to_s}"
352
- break
306
+ warn "module_const.class: #{module_const.class.inspect}"
353
307
  end
354
- else
355
- warn "module_const.class: #{module_const.class.inspect}"
356
308
  end
357
309
  end
358
310
  end
359
- end
360
-
361
- def register_bundle( inst, bundle_name )
362
- bundle_name = bundle_name.to_sym
363
- if @registry.has_key?( bundle_name )
364
- if registry[ bundle_name ] != inst
365
- warn "Tried to register a conflicting bundle name: #{bundle_name.inspect}; ignoring"
311
+
312
+ # Registers plugin class +inst+ into the registry using +bundle_name+
313
+ def register_bundle( inst, bundle_name )
314
+ bundle_name = bundle_name.to_sym
315
+ if @registry.has_key?( bundle_name )
316
+ if registry[ bundle_name ] != inst
317
+ warn "Tried to register a conflicting bundle name: #{bundle_name.inspect}; ignoring"
318
+ else
319
+ warn "Use @plugins.register_alias to register more than one name per plugin."
320
+ register_alias( inst.name.to_sym, bundle_name )
321
+ end
366
322
  else
367
- warn "Use @plugins.register_alias to register more than one name per plugin."
368
- register_alias( inst.name.to_sym, bundle_name )
369
- end
370
- else
371
- inst.init if inst.respond_to? :init and not inst.inited
372
- @registry[ bundle_name ] = inst
373
- if inst.respond_to?( :match ) and ( inst.respond_to?( :get ) or inst.respond_to?( :post ) )
374
- puts " --- servlet: #{bundle_name.inspect}, #{inst.respond_to?(:match)}, #{inst.post}" if bundle_name == :welcome
375
- @servlets.push( bundle_name )
376
- end
377
- end
378
- end
379
-
380
- def register_alias( bundle_name, alias_name )
381
- if @aliases.has_key?( alias_name.to_sym )
382
- warn "Alias already taken: #{alias_name.inspect}"
383
- else
384
- @aliases[ alias_name ] = bundle_name.to_sym
385
- end
386
- end
387
-
388
- def plugin_error( e, err_location, err_location_descr, eval_repl=false )
389
- err_msg = [
390
- "*"*40,
391
- err_location,
392
- err_location_descr,
393
- "#{e.class.to_s}, #{e.message}",
394
- "Backtrace:",
395
- "\t"+e.backtrace.join("\n\t"),
396
- "*"*40
397
- ].join("\n")+"\n"
398
- if eval_repl
399
- puts
400
- puts "plugin: #{eval_repl}"
401
- puts
402
- err_msg = err_msg.gsub(/^\t\(eval\)\:/s,"\t#{eval_repl}:")
403
- end
404
- $stderr.write( err_msg )
405
- end
406
-
407
- def match_servlet_uri( uri, req_type=:get )
408
- match_score = {}
409
- @servlets.each do | servlet_name |
410
- servlet = @registry[ servlet_name ]
411
- next unless servlet.respond_to?( req_type )
412
- begin
413
- if servlet.match( uri, req_type )
414
- score = servlet.score
415
- match_score[ score ] = [] unless match_score.has_key? score
416
- match_score[ score ].push( servlet_name )
323
+ inst.init if inst.respond_to? :init and not inst.inited
324
+ @registry[ bundle_name ] = inst
325
+ if inst.respond_to?( :match ) and ( inst.respond_to?( :get ) or inst.respond_to?( :post ) )
326
+ puts " --- servlet: #{bundle_name.inspect}, #{inst.respond_to?(:match)}, #{inst.post}" if bundle_name == :welcome
327
+ @servlets.push( bundle_name )
417
328
  end
418
- rescue => e
419
- plugin_error(
420
- e,
421
- "RSence::PluginManager.match_servlet_uri",
422
- "servlet: #{servlet_name.inspect}, req_type: #{req_type.inspect}, uri: #{uri.inspect}",
423
- servlet_name
424
- )
425
329
  end
426
330
  end
427
- match_scores = match_score.keys.sort
428
- if match_scores.empty?
429
- return false
430
- else
431
- matches_order = []
432
- matches_best = match_score[ match_scores[0] ]
433
- if matches_best.size > 1
434
- matches_best = matches_best[ rand( matches_best.size ) ]
331
+
332
+ # Registers alias name for a plugin bundle.
333
+ def register_alias( bundle_name, alias_name )
334
+ if @aliases.has_key?( alias_name.to_sym )
335
+ warn "Alias already taken: #{alias_name.inspect}"
435
336
  else
436
- matches_best = matches_best.first
337
+ @aliases[ alias_name ] = bundle_name.to_sym
437
338
  end
438
- matches_order.push( matches_best )
439
- match_score.keys.sort.each do |match_n|
440
- match_score[ match_n ].each do | match_name |
441
- matches_order.push( match_name ) unless matches_order.include? match_name
442
- end
339
+ end
340
+
341
+ # Prettier error handling.
342
+ def plugin_error( e, err_location, err_location_descr, eval_repl=false )
343
+ err_msg = [
344
+ "*"*40,
345
+ err_location,
346
+ err_location_descr,
347
+ "#{e.class.to_s}, #{e.message}",
348
+ "Backtrace:",
349
+ "\t"+e.backtrace.join("\n\t"),
350
+ "*"*40
351
+ ].join("\n")+"\n"
352
+ if eval_repl
353
+ puts
354
+ puts "plugin: #{eval_repl}"
355
+ puts
356
+ err_msg = err_msg.gsub(/^\t\(eval\)\:/s,"\t#{eval_repl}:")
443
357
  end
444
- return matches_order
358
+ $stderr.write( err_msg )
445
359
  end
446
- end
447
-
448
- def delegate( method_name, *args )
449
- @registry.each do | plugin_name, plugin |
450
- if plugin.respond_to?( method_name )
360
+
361
+ # Search servlets that match the +uri+ and +req_type+
362
+ def match_servlet_uri( uri, req_type=:get )
363
+ match_score = {}
364
+ @servlets.each do | servlet_name |
365
+ servlet = @registry[ servlet_name ]
366
+ next unless servlet.respond_to?( req_type )
451
367
  begin
452
- plugin.send( method_name, *args )
368
+ if servlet.match( uri, req_type )
369
+ score = servlet.score
370
+ match_score[ score ] = [] unless match_score.has_key? score
371
+ match_score[ score ].push( servlet_name )
372
+ end
453
373
  rescue => e
454
374
  plugin_error(
455
375
  e,
456
- "RSence::PluginManager.delegate error",
457
- "plugin_name: #{plugin_name.inspect}, method_name: #{method_name.inspect}",
458
- plugin_name
376
+ "RSence::PluginManager.match_servlet_uri",
377
+ "servlet: #{servlet_name.inspect}, req_type: #{req_type.inspect}, uri: #{uri.inspect}",
378
+ servlet_name
459
379
  )
460
380
  end
461
381
  end
382
+ match_scores = match_score.keys.sort
383
+ if match_scores.empty?
384
+ return false
385
+ else
386
+ matches_order = []
387
+ matches_best = match_score[ match_scores[0] ]
388
+ if matches_best.size > 1
389
+ matches_best = matches_best[ rand( matches_best.size ) ]
390
+ else
391
+ matches_best = matches_best.first
392
+ end
393
+ matches_order.push( matches_best )
394
+ match_score.keys.sort.each do |match_n|
395
+ match_score[ match_n ].each do | match_name |
396
+ matches_order.push( match_name ) unless matches_order.include? match_name
397
+ end
398
+ end
399
+ return matches_order
400
+ end
462
401
  end
463
- end
464
-
465
- def shutdown
466
- delegate( :flush )
467
- delegate( :close )
468
- end
469
-
470
- def call( plugin_name, method_name, *args )
471
- plugin_name = plugin_name.to_sym
472
- if @registry.has_key?( plugin_name )
473
- if @registry[ plugin_name ].respond_to?( method_name )
474
- return @registry[ plugin_name ].send( method_name, *args )
402
+
403
+ # Delegates +method_name+ with +args+ to any loaded
404
+ # plugin that responds to the method.
405
+ def delegate( method_name, *args )
406
+ @registry.each do | plugin_name, plugin |
407
+ if plugin.respond_to?( method_name )
408
+ begin
409
+ plugin.send( method_name, *args )
410
+ rescue => e
411
+ plugin_error(
412
+ e,
413
+ "RSence::PluginManager.delegate error",
414
+ "plugin_name: #{plugin_name.inspect}, method_name: #{method_name.inspect}",
415
+ plugin_name
416
+ )
417
+ end
418
+ end
419
+ end
420
+ end
421
+
422
+ # Delegates the +flush+ and +close+ methods to any
423
+ # loaded plugins, in that order.
424
+ def shutdown
425
+ delegate( :flush )
426
+ delegate( :close )
427
+ end
428
+
429
+ # Calls the method +method_name+ with args +args+ of the plugin +plugin_name+.
430
+ # Returns false, if no such plugin or method exists.
431
+ def call( plugin_name, method_name, *args )
432
+ plugin_name = plugin_name.to_sym
433
+ if @registry.has_key?( plugin_name )
434
+ if @registry[ plugin_name ].respond_to?( method_name )
435
+ return @registry[ plugin_name ].send( method_name, *args )
436
+ else
437
+ puts "No method #{method_name.inspect} for plugin #{plugin_name.inspect}"
438
+ return false
439
+ end
475
440
  else
476
- puts "No method #{method_name.inspect} for plugin #{plugin_name.inspect}"
441
+ puts "No such plugin: #{plugin_name.inspect}"
477
442
  return false
478
443
  end
479
- else
480
- puts "No such plugin: #{plugin_name.inspect}"
481
- return false
482
444
  end
483
- end
484
-
485
- alias run_plugin call
486
-
487
- def match_servlet( req_type, req, resp, session )
488
- req_uri = req.fullpath
489
- matches_order = match_servlet_uri( req_uri, req_type )
490
- return false unless matches_order
491
- matches_order.each do |servlet_name|
492
- # puts "servlet name: #{servlet_name.inspect}" if RSence.args[:debug]
493
- begin
494
- @registry[servlet_name].send( req_type, req, resp, session )
495
- return true
496
- rescue => e
497
- plugin_error(
498
- e,
499
- "RSence::PluginManager.match_servlet",
500
- "servlet_name: #{servlet_name.inspect}, req_type: #{req_type.inspect}",
501
- servlet_name
502
- )
503
- next
445
+ alias run_plugin call
446
+
447
+ # Calls the servlet that matches the +req_type+ and +req.fullpath+ with
448
+ # the highest score.
449
+ def match_servlet( req_type, req, resp, session )
450
+ req_uri = req.fullpath
451
+ matches_order = match_servlet_uri( req_uri, req_type )
452
+ return false unless matches_order
453
+ matches_order.each do |servlet_name|
454
+ begin
455
+ @registry[servlet_name].send( req_type, req, resp, session )
456
+ return true
457
+ rescue => e
458
+ plugin_error(
459
+ e,
460
+ "RSence::PluginManager.match_servlet",
461
+ "servlet_name: #{servlet_name.inspect}, req_type: #{req_type.inspect}",
462
+ servlet_name
463
+ )
464
+ next
465
+ end
504
466
  end
467
+ return false
505
468
  end
506
- return false
507
469
  end
508
-
509
- end
510
-
511
470
  end