plugin-loader 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
1
+ # command.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #The command format takes '$' to be a command, executes it, and
21
+ #returns an array of lines of standard output.
22
+ # {
23
+ # "format" => "command",
24
+ # "$" => "COMMAND"
25
+ # }
26
+ require 'plugin/format'
27
+
28
+ #Depends: libescape-ruby
29
+ require 'escape'
30
+
31
+ Plugin::Format.add 'command' do |exec, args, opts|
32
+ IO.popen Escape.shell_command([exec.to_s, *args]).to_s do |handle|
33
+ return handle.read.split("\n")
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ # data.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #data is a very simple plugin format that just returns the data structure
21
+ #referred to by the '$' key in the plugin metadata file:
22
+ # {
23
+ # "format" : "data",
24
+ # "$" : ...
25
+ # }
26
+ #The data can be any type supported by JSON, including number, string, array,
27
+ #hash(object) and boolean.
28
+ require 'plugin/format'
29
+
30
+ Plugin::Format.add 'data' do |exec, args, opts|
31
+ exec
32
+ end
@@ -0,0 +1,67 @@
1
+ # dbus.rb
2
+ #
3
+ # Defines a plugin format that works by connecting to a dbus service.
4
+ #
5
+ # Copyright 2010 David Green <david4dev@gmail.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301, USA.
21
+ #
22
+ #
23
+ #A plugin in dbus format has a general metadata file format of:
24
+ # {
25
+ # 'format' : 'dbus',
26
+ # '$' : [service, object, interface, method]
27
+ # }
28
+ #For example:
29
+ # {
30
+ # "format" : "dbus",
31
+ # "$" : [
32
+ # "org.gnome.Rhythmbox",
33
+ # "/org/gnome/Rhythmbox/Player",
34
+ # "org.gnome.Rhythmbox.Player",
35
+ # "getPlayingUri"
36
+ # ]
37
+ # }
38
+ #describes a plugin that gets the current playing song in Rhythmbox.
39
+ #
40
+ #The dbus format uses the dbus session bus.
41
+ #It only works with dbus services that can be introspected (which is almost all of them).
42
+ require 'plugin/format'
43
+
44
+ #Depends: libdbus-ruby
45
+ require 'dbus'
46
+
47
+ module Plugin
48
+
49
+ Format.add 'dbus' do |exec, args, opts|
50
+ service = exec[0]
51
+ object = exec[1]
52
+ iface = exec[2]
53
+ method = exec[3]
54
+
55
+ obj = DBus::SessionBus.
56
+ instance.
57
+ service(service).
58
+ object(object)
59
+
60
+ obj.introspect
61
+
62
+ obj[iface].
63
+ method(method).
64
+ call(*args)
65
+ end
66
+
67
+ end
@@ -0,0 +1,48 @@
1
+ # ruby.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #The ruby format allows plugins to be written in ruby.
21
+ #The '$' key refers to the ruby file that should be loaded.
22
+ #The metadata file has the following format:
23
+ # {
24
+ # "format" : "ruby",
25
+ # "$" : "ruby_lib"
26
+ # }
27
+ #The ruby file should look something like:
28
+ # Plugin.new do |*args|
29
+ # #some code
30
+ # end
31
+ require 'plugin/format'
32
+
33
+ module Plugin
34
+
35
+ _ruby_plugin = lambda do |*args|
36
+ args
37
+ end
38
+
39
+ def self.new &b
40
+ _ruby_plugin = b
41
+ end
42
+
43
+ Format.add 'ruby' do |exec, args, opts|
44
+ load exec
45
+ _ruby_plugin.call *args
46
+ end
47
+
48
+ end
@@ -0,0 +1,35 @@
1
+ # script.rb
2
+ #
3
+ # Copyright 2010 David Green <david4dev@gmail.com>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
+ # MA 02110-1301, USA.
19
+ #
20
+ #The script format takes '$' to be an executable in the @script_dir folder.
21
+ #The script is executed and an array of lines of standard output is returned.
22
+ # {
23
+ # "format" => "command",
24
+ # "$" => "COMMAND"
25
+ # }
26
+ require 'plugin/format'
27
+
28
+ #Depends: libescape-ruby
29
+ require 'escape'
30
+
31
+ Plugin::Format.add 'script' do |exec, args, opts|
32
+ IO.popen Escape.shell_command(["#{opts[:dir] || '/usr/bin'}/#{exec}", *args]).to_s do |handle|
33
+ return handle.read.split("\n")
34
+ end
35
+ end
@@ -0,0 +1,68 @@
1
+ # format.rb
2
+ #
3
+ # Defines a class allowing new plugin formats to be added.
4
+ #
5
+ # Copyright 2010 David Green <david4dev@gmail.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301, USA.
21
+
22
+
23
+ module Plugin
24
+
25
+ #An instance of this class represents a plugin format.
26
+ class Format
27
+ @@formats = {}
28
+ #To create a new annonymous plugin format:
29
+ # Plugin::Format.new do |exec, args, opts|
30
+ # ...
31
+ # return return_data
32
+ # end
33
+ #Argument 'exec' provides the data in the '$' key of the plugin metadata file.
34
+ #Argument 'args' is an array of arguments passed to this format by a Plugin::Loader instance when its run method is called.
35
+ #Argument 'opts' is a hash of options from Plugin::Loader that may be required by a plugin format. At present opts conatins the following keys:
36
+ # :plugin_dir
37
+ # :data_dir
38
+ # :script_dir
39
+ #These are the same as the options given when the Plugin::Loader was initialized.
40
+ #
41
+ #Plugin::Format.add should be used to create a new plugin format because the format is given a name.
42
+ def initialize &b
43
+ @block = b
44
+ end
45
+ #Creates a lambda function from the exec value and opts hash.
46
+ #When the lambda function is called, its arguments become 'args' and
47
+ #the block given at initialize is executed.
48
+ def new exec, opts={}
49
+ lambda do |*args|
50
+ @block.call exec, args, opts
51
+ end
52
+ end
53
+ #Creates a named plugin format using the same rules as Plugin::Format.new:
54
+ # Plugin::Format.add "name" do |exec, args, opts|
55
+ # ...
56
+ # return return_data
57
+ # end
58
+ def self.add name, &b
59
+ @@formats[name] = self.new &b
60
+ end
61
+ #Returns the format called 'name':
62
+ # Plugin::Format['name']
63
+ def self.[] name
64
+ @@formats[name]
65
+ end
66
+ end
67
+
68
+ end
@@ -0,0 +1,130 @@
1
+ # loader.rb
2
+ #
3
+ # Provides a class for loading plugins into a program.
4
+ #
5
+ # Copyright 2010 David Green <david4dev@gmail.com>
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License
18
+ # along with this program; if not, write to the Free Software
19
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
+ # MA 02110-1301, USA.
21
+ require 'plugin/format'
22
+
23
+ #Depends: libjson-ruby
24
+ require 'json'
25
+
26
+ module Plugin
27
+
28
+ #Using an instance of this class, you can control what plugins are
29
+ #loaded into your program.
30
+ class Loader
31
+ #OPTIONS:
32
+ #
33
+ # :allowed_formats => [...] #optional; default is an array of all available plugin formats
34
+ #- Defines an array of names (strings) of formats that plugins for this instance can be written in.
35
+ #
36
+ # :data_dir => '/usr/share/appname' #required
37
+ #- Defines the directory in which the data for this instance is stored in the file system.
38
+ #
39
+ # :plugin_dir => '' #optional; default is "#{@data_dir}/plugins"
40
+ #- Defines the directory in which the plugin metadata files are stored
41
+ #
42
+ # :script_dir => '' #optional; default is "#{@data_dir}/scripts"
43
+ #- Defines the directory in which excecutables (potentially used by plugins) are stored.
44
+ def initialize opts={}
45
+ @available_formats = $:.map do |path|
46
+ Dir.glob("#{path}/plugin/format/*.rb").map! do |rbfile|
47
+ File.basename(rbfile).sub!(/\.rb$/, '')
48
+ end
49
+ end
50
+ @available_formats.flatten!
51
+ @allowed_formats = opts[:allowed_formats] ? (opts[:allowed_formats] & available_formats) : available_formats
52
+ @allowed_formats.each do |fmt|
53
+ require "plugin/format/#{fmt}"
54
+ end
55
+ @data_dir = opts[:data_dir]
56
+ @plugin_dir = opts[:plugin_dir] || "#{@data_dir}/plugins"
57
+ @script_dir = opts[:script_dir] || "#{@data_dir}/scripts"
58
+ @plugins = {}
59
+ end
60
+ #Loads a plugin called 'name' of type 'type'.
61
+ #It does this by reading the metadata file: "#{@plugin_dir}/name.type".
62
+ #Plugin types should be considered namespaces for one or more plugins.
63
+ #Plugin names are the unique identification of a plugin within a particular type.
64
+ #Plugins are similar to functions - they are excecuted with arguments a value (which can be a complex data structure such as hash or array if needed).
65
+ #load does not excecute a plugin but it once loaded
66
+ #a plugin can be excecuted with the run method.
67
+ #
68
+ #The metadata files are in a JSON format:
69
+ # {
70
+ # "format" => "FORMAT_NAME",
71
+ # "$" => ...
72
+ # }
73
+ #The 'format' key is a string that defines the name of the format of the plugin. If load loads a plugin without the 'format' key, an exception is raised.
74
+ #If the format is not available or is not allowed (see: initailize), an exception is raised.
75
+ #See Plugin::Format for more details on plugin formats.
76
+ #The '$' key can be any data structure (most commonly a string) and is used by the format declaration to excecute a plugin. See the individual format declarations in plugin/format/*.rb for details of individual formats. If the '$' key is missing, an exception is raised.
77
+ def load name, type
78
+ File.open "#{@plugin_dir}/#{name}.#{type}" do |f|
79
+ data = JSON.parse(f.read)
80
+ unless data.has_key? '$'
81
+ raise "Plugin #{type} plugin '#{name}' has an invalid metadata file. It is missing the required '$' key!"
82
+ end
83
+ unless data.has_key? 'format'
84
+ raise "Plugin #{type} plugin '#{name}' has an invalid metadata file. It is missing the required 'format' key!"
85
+ end
86
+ unless @plugins.has_key? type
87
+ @plugins[type] = {}
88
+ end
89
+ format = Format[data['format']]
90
+ if format.nil?
91
+ raise "Plugin format #{data['format']} does not exist or is disabled!"
92
+ end
93
+ @plugins[type][name] = format.new data['$'],
94
+ :script_dir => @script_dir,
95
+ :data_dir => @data_dir,
96
+ :plugin_dir => @plugin_dir
97
+ end
98
+ end
99
+ #Unloads a plugin of name 'name' and type 'type'.
100
+ def unload name, type
101
+ @plugins[type].delete name
102
+ end
103
+ #Loads all plugins of type 'type'.
104
+ def load_type type
105
+ Dir.glob("#{@plugin_dir}/*.#{type}").each do |file|
106
+ self.load file
107
+ end
108
+ end
109
+ #Unloads all plugins of type 'type'.
110
+ def unload_type type
111
+ @plugins.delete type
112
+ end
113
+ #Loads all plugins.
114
+ def load_all
115
+ Dir.glob("#{@plugin_dir}/*").each do |file|
116
+ self.load file
117
+ end
118
+ end
119
+ #Unloads all plugins.
120
+ def unload_all
121
+ @plugins.clear
122
+ end
123
+ #Excecutes the plugin of type 'type' called 'name', passing in any other arguments.
124
+ #The return value of the plugin is returned.
125
+ def run name, type, *args
126
+ @plugins[type][name].call *args
127
+ end
128
+ end
129
+
130
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: plugin-loader
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - David Green
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-09-25 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: dbus
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: escape
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: |-
46
+ plugin-loader can be used to extend a program written in ruby by using plugins.
47
+ Plugins can be written in ruby or can be external resources.
48
+ email: david4dev@gmail.com
49
+ executables: []
50
+
51
+ extensions: []
52
+
53
+ extra_rdoc_files: []
54
+
55
+ files:
56
+ - lib/plugin/format/dbus.rb
57
+ - lib/plugin/format/script.rb
58
+ - lib/plugin/format/ruby.rb
59
+ - lib/plugin/format/data.rb
60
+ - lib/plugin/format/command.rb
61
+ - lib/plugin/format.rb
62
+ - lib/plugin/loader.rb
63
+ has_rdoc: true
64
+ homepage: https://launchpad.net/libplugin-loader-ruby
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options: []
69
+
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 1.8.1
77
+ version:
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ requirements: []
85
+
86
+ rubyforge_project:
87
+ rubygems_version: 1.3.5
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Library for creating extensible ruby applications
91
+ test_files: []
92
+