rsence 2.0.0.6.pre → 2.0.0.7.pre

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.
@@ -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