pluginfactory 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile ADDED
@@ -0,0 +1,252 @@
1
+ #!rake
2
+ #
3
+ # PluginFactory rakefile
4
+ #
5
+ # Based on various other Rakefiles, especially one by Ben Bleything
6
+ #
7
+ # Copyright (c) 2008 The FaerieMUD Consortium
8
+ #
9
+ # Authors:
10
+ # * Michael Granger <ged@FaerieMUD.org>
11
+ #
12
+
13
+ BEGIN {
14
+ require 'pathname'
15
+ basedir = Pathname.new( __FILE__ ).dirname
16
+
17
+ libdir = basedir + "lib"
18
+ extdir = basedir + "ext"
19
+
20
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
21
+ $LOAD_PATH.unshift( extdir.to_s ) unless $LOAD_PATH.include?( extdir.to_s )
22
+ }
23
+
24
+
25
+ require 'rbconfig'
26
+ require 'rubygems'
27
+ require 'rake'
28
+ require 'rake/rdoctask'
29
+ require 'rake/testtask'
30
+ require 'rake/packagetask'
31
+ require 'rake/clean'
32
+
33
+ $dryrun = false
34
+
35
+ ### Config constants
36
+ BASEDIR = Pathname.new( __FILE__ ).dirname.relative_path_from( Pathname.getwd )
37
+ LIBDIR = BASEDIR + 'lib'
38
+ EXTDIR = BASEDIR + 'ext'
39
+ DOCSDIR = BASEDIR + 'docs'
40
+ PKGDIR = BASEDIR + 'pkg'
41
+
42
+ PKG_NAME = 'pluginfactory'
43
+ PKG_SUMMARY = 'A mixin for making plugin classes'
44
+ VERSION_FILE = LIBDIR + 'pluginfactory.rb'
45
+ PKG_VERSION = VERSION_FILE.read[ /VERSION = '(\d+\.\d+\.\d+)'/, 1 ]
46
+ PKG_FILE_NAME = "#{PKG_NAME.downcase}-#{PKG_VERSION}"
47
+ GEM_FILE_NAME = "#{PKG_FILE_NAME}.gem"
48
+
49
+ ARTIFACTS_DIR = Pathname.new( ENV['CC_BUILD_ARTIFACTS'] || 'artifacts' )
50
+
51
+ TEXT_FILES = %w( Rakefile ChangeLog README LICENSE ).collect {|filename| BASEDIR + filename }
52
+ LIB_FILES = Pathname.glob( LIBDIR + '**/*.rb' ).delete_if {|item| item =~ /\.svn/ }
53
+ EXT_FILES = Pathname.glob( EXTDIR + '**/*.{c,h,rb}' ).delete_if {|item| item =~ /\.svn/ }
54
+
55
+ SPECDIR = BASEDIR + 'spec'
56
+ SPEC_FILES = Pathname.glob( SPECDIR + '**/*_spec.rb' ).delete_if {|item| item =~ /\.svn/ }
57
+
58
+ TESTDIR = BASEDIR + 'tests'
59
+ TEST_FILES = Pathname.glob( TESTDIR + '**/*.tests.rb' ).delete_if {|item| item =~ /\.svn/ }
60
+
61
+ RAKE_TASKDIR = BASEDIR + 'rake'
62
+ RAKE_TASKLIBS = Pathname.glob( RAKE_TASKDIR + '*.rb' )
63
+
64
+ LOCAL_RAKEFILE = BASEDIR + 'Rakefile.local'
65
+
66
+ EXTRA_PKGFILES = []
67
+
68
+ RELEASE_FILES = TEXT_FILES +
69
+ SPEC_FILES +
70
+ TEST_FILES +
71
+ LIB_FILES +
72
+ EXT_FILES +
73
+ RAKE_TASKLIBS +
74
+ EXTRA_PKGFILES
75
+
76
+ RELEASE_FILES << LOCAL_RAKEFILE if LOCAL_RAKEFILE.exist?
77
+
78
+ COVERAGE_MINIMUM = ENV['COVERAGE_MINIMUM'] ? Float( ENV['COVERAGE_MINIMUM'] ) : 85.0
79
+ RCOV_EXCLUDES = 'spec,tests,/Library/Ruby,/var/lib,/usr/local/lib'
80
+ RCOV_OPTS = [
81
+ '--exclude', RCOV_EXCLUDES,
82
+ '--xrefs',
83
+ '--save',
84
+ '--callsites',
85
+ #'--aggregate', 'coverage.data' # <- doesn't work as of 0.8.1.2.0
86
+ ]
87
+
88
+
89
+ # Subversion constants -- directory names for releases and tags
90
+ SVN_TRUNK_DIR = 'trunk'
91
+ SVN_RELEASES_DIR = 'releases'
92
+ SVN_BRANCHES_DIR = 'branches'
93
+ SVN_TAGS_DIR = 'tags'
94
+
95
+ SVN_DOTDIR = BASEDIR + '.svn'
96
+ SVN_ENTRIES = SVN_DOTDIR + 'entries'
97
+
98
+
99
+ ### Load some task libraries that need to be loaded early
100
+ require RAKE_TASKDIR + 'helpers.rb'
101
+ require RAKE_TASKDIR + 'svn.rb'
102
+ require RAKE_TASKDIR + 'verifytask.rb'
103
+
104
+ # Define some constants that depend on the 'svn' tasklib
105
+ PKG_BUILD = get_svn_rev( BASEDIR ) || 0
106
+ SNAPSHOT_PKG_NAME = "#{PKG_FILE_NAME}.#{PKG_BUILD}"
107
+ SNAPSHOT_GEM_NAME = "#{SNAPSHOT_PKG_NAME}.gem"
108
+
109
+ # Documentation constants
110
+ RDOC_OPTIONS = [
111
+ '-w', '4',
112
+ '-SHN',
113
+ '-i', '.',
114
+ '-m', 'README',
115
+ '-W', 'http://deveiate.org/projects/PluginFactory//browser/trunk/'
116
+ ]
117
+
118
+ # Release constants
119
+ SMTP_HOST = 'mail.faeriemud.org'
120
+ SMTP_PORT = 465 # SMTP + SSL
121
+
122
+ # Project constants
123
+ PROJECT_HOST = 'deveiate.org'
124
+ PROJECT_PUBDIR = "/usr/local/www/public/code"
125
+ PROJECT_DOCDIR = "#{PROJECT_PUBDIR}/#{PKG_NAME}"
126
+ PROJECT_SCPURL = "#{PROJECT_HOST}:#{PROJECT_DOCDIR}"
127
+
128
+ # Rubyforge stuff
129
+ RUBYFORGE_GROUP = 'deveiate'
130
+ RUBYFORGE_PROJECT = 'pluginfactory'
131
+
132
+ # Gem dependencies: gemname => version
133
+ DEPENDENCIES = {
134
+ }
135
+
136
+ # Non-gem requirements: packagename => version
137
+ REQUIREMENTS = {
138
+ }
139
+
140
+ # RubyGem specification
141
+ GEMSPEC = Gem::Specification.new do |gem|
142
+ gem.name = PKG_NAME.downcase
143
+ gem.version = PKG_VERSION
144
+
145
+ gem.summary = PKG_SUMMARY
146
+ gem.description = <<-EOD
147
+ PluginFactory is a mixin module that turns an including class into a factory for
148
+ its derivatives, capable of searching for and loading them by name. This is
149
+ useful when you have an abstract base class which defines an interface and basic
150
+ functionality for a part of a larger system, and a collection of subclasses
151
+ which implement the interface for different underlying functionality.
152
+ EOD
153
+
154
+ gem.authors = 'Michael Granger'
155
+ gem.email = 'ged@FaerieMUD.org'
156
+ gem.homepage = 'http://deveiate.org/projects/PluginFactory/'
157
+ gem.rubyforge_project = RUBYFORGE_PROJECT
158
+
159
+ gem.has_rdoc = true
160
+ gem.rdoc_options = RDOC_OPTIONS
161
+
162
+ gem.files = RELEASE_FILES.
163
+ collect {|f| f.relative_path_from(BASEDIR).to_s }
164
+ gem.test_files = SPEC_FILES.
165
+ collect {|f| f.relative_path_from(BASEDIR).to_s }
166
+
167
+ DEPENDENCIES.each do |name, version|
168
+ version = '>= 0' if version.length.zero?
169
+ gem.add_dependency( name, version )
170
+ end
171
+
172
+ REQUIREMENTS.each do |name, version|
173
+ gem.requirements << [ name, version ].compact.join(' ')
174
+ end
175
+ end
176
+
177
+ $trace = Rake.application.options.trace ? true : false
178
+ $dryrun = Rake.application.options.dryrun ? true : false
179
+
180
+
181
+ # Load any remaining task libraries
182
+ RAKE_TASKLIBS.each do |tasklib|
183
+ next if tasklib =~ %r{/(helpers|svn|verifytask)\.rb$}
184
+ begin
185
+ require tasklib
186
+ rescue ScriptError => err
187
+ fail "Task library '%s' failed to load: %s: %s" %
188
+ [ tasklib, err.class.name, err.message ]
189
+ trace "Backtrace: \n " + err.backtrace.join( "\n " )
190
+ rescue => err
191
+ log "Task library '%s' failed to load: %s: %s. Some tasks may not be available." %
192
+ [ tasklib, err.class.name, err.message ]
193
+ trace "Backtrace: \n " + err.backtrace.join( "\n " )
194
+ end
195
+ end
196
+
197
+ # Load any project-specific rules defined in 'Rakefile.local' if it exists
198
+ import LOCAL_RAKEFILE if LOCAL_RAKEFILE.exist?
199
+
200
+
201
+ #####################################################################
202
+ ### T A S K S
203
+ #####################################################################
204
+
205
+ ### Default task
206
+ task :default => [:clean, :local, :spec, :rdoc, :package]
207
+
208
+ ### Task the local Rakefile can append to -- no-op by default
209
+ task :local
210
+
211
+
212
+ ### Task: clean
213
+ CLEAN.include 'coverage'
214
+ CLOBBER.include 'artifacts', 'coverage.info', PKGDIR
215
+
216
+ # Target to hinge on ChangeLog updates
217
+ file SVN_ENTRIES
218
+
219
+ ### Task: changelog
220
+ file 'ChangeLog' => SVN_ENTRIES.to_s do |task|
221
+ log "Updating #{task.name}"
222
+
223
+ changelog = make_svn_changelog()
224
+ File.open( task.name, 'w' ) do |fh|
225
+ fh.print( changelog )
226
+ end
227
+ end
228
+
229
+
230
+ ### Task: cruise (Cruisecontrol task)
231
+ desc "Cruisecontrol build"
232
+ task :cruise => [:clean, :spec, :package] do |task|
233
+ raise "Artifacts dir not set." if ARTIFACTS_DIR.to_s.empty?
234
+ artifact_dir = ARTIFACTS_DIR.cleanpath
235
+ artifact_dir.mkpath
236
+
237
+ $stderr.puts "Copying coverage stats..."
238
+ FileUtils.cp_r( 'coverage', artifact_dir )
239
+
240
+ $stderr.puts "Copying packages..."
241
+ FileUtils.cp_r( FileList['pkg/*'].to_a, artifact_dir )
242
+ end
243
+
244
+
245
+ desc "Update the build system to the latest version"
246
+ task :update_build do
247
+ log "Updating the build system"
248
+ sh 'svn', 'up', RAKE_TASKDIR
249
+ log "Updating the Rakefile"
250
+ sh 'rake', '-f', RAKE_TASKDIR + 'Metarakefile'
251
+ end
252
+
data/lib/pluginfactory.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env ruby -w
2
- #
2
+
3
+ ### An exception class for PluginFactory specific errors.
4
+ class FactoryError < RuntimeError; end
5
+
3
6
  # This module contains the PluginFactory mixin. Including PluginFactory in your
4
7
  # class turns it into a factory for its derivatives, capable of searching for
5
8
  # and loading them by name. This is useful when you have an abstract base class
@@ -18,7 +21,9 @@
18
21
  #
19
22
  # == Creation Argument Variants
20
23
  #
21
- # The +create+ class method added to your class by PluginFactory searches for your module using
24
+ # The +create+ class method added to your class by PluginFactory searches for
25
+ # your module using the $LOAD_PATH that require uses. See the README for a
26
+ # detailed explanation.
22
27
  #
23
28
  # == Synopsis
24
29
  #
@@ -60,38 +65,24 @@
60
65
  #
61
66
  # == Subversion ID
62
67
  #
63
- # $Id: pluginfactory.rb 38 2007-03-13 18:20:58Z deveiant $
68
+ # $Id: pluginfactory.rb 52 2008-08-13 21:58:41Z deveiant $
64
69
  #
65
70
  # == Authors
66
71
  #
67
72
  # * Martin Chase <stillflame@FaerieMUD.org>
68
73
  # * Michael Granger <ged@FaerieMUD.org>
69
74
  #
70
- #:include: COPYRIGHT
75
+ # :include: LICENSE
71
76
  #
72
77
  #---
73
78
  #
74
- # Please see the file docs/COPYRIGHT for licensing details.
79
+ # Please see the file LICENSE for licensing details.
75
80
  #
76
-
77
-
78
- ### An exception class for PluginFactory specific errors.
79
- class FactoryError < RuntimeError
80
- def initialize( *args )
81
- if ! args.empty?
82
- msg = args.collect {|a| a.to_s}.join
83
- super( msg )
84
- else
85
- super( message )
86
- end
87
- end
88
- end # class FactoryError
89
-
90
-
91
- ### A mixin that adds PluginFactory class methods to a base class, so that
92
- ### subclasses may be instantiated by name.
93
81
  module PluginFactory
94
82
 
83
+ VERSION = '1.0.3'
84
+
85
+
95
86
  ### A callback for logging the various debug and information this module
96
87
  ### has to log. Should take two arguments, the log level, possibly as a
97
88
  ### symbol, and the log message itself.
@@ -100,24 +91,24 @@ module PluginFactory
100
91
  attr_accessor :logger_callback
101
92
  end
102
93
 
103
- ### If the logger callback is set, use it to pass on a log entry. First argument is
104
- def self::log(level, *msg)
105
- @logger_callback.call(level, msg.join) if @logger_callback
94
+ ### If the logger callback is set, use it to pass on a log entry. First
95
+ ### argument is a 'level' which is passed to the logging callback. Any
96
+ ### remaining arguments will be joined and passed as a single second
97
+ ### argument to the callback.
98
+ def self::log( level, *msg )
99
+ @logger_callback.call( level, msg.join ) if @logger_callback
106
100
  end
107
101
 
108
102
 
109
- ### Inclusion callback -- extends the including class.
103
+ ### Inclusion callback -- extends the including class. This is here so you can
104
+ ### either 'include' or 'extend'.
110
105
  def self::included( klass )
111
106
  klass.extend( self )
112
107
  end
113
108
 
114
109
 
115
- ### Raise an exception if the object being extended is anything but a
116
- ### class.
110
+ ### Add the @derivatives instance variable to including classes.
117
111
  def self::extend_object( obj )
118
- unless obj.is_a?( Class )
119
- raise TypeError, "Cannot extend a #{obj.class.name}", caller(1)
120
- end
121
112
  obj.instance_variable_set( :@derivatives, {} )
122
113
  super
123
114
  end
@@ -130,23 +121,23 @@ module PluginFactory
130
121
  ### Return the Hash of derivative classes, keyed by various versions of
131
122
  ### the class name.
132
123
  def derivatives
133
- ancestors.each {|klass|
124
+ ancestors.each do |klass|
134
125
  if klass.instance_variables.include?( "@derivatives" )
135
- break klass.instance_variable_get( :@derivatives )
126
+ return klass.instance_variable_get( :@derivatives )
136
127
  end
137
- }
128
+ end
138
129
  end
139
130
 
140
131
 
141
132
  ### Returns the type name used when searching for a derivative.
142
133
  def factory_type
143
134
  base = nil
144
- self.ancestors.each {|klass|
135
+ self.ancestors.each do |klass|
145
136
  if klass.instance_variables.include?( "@derivatives" )
146
137
  base = klass
147
138
  break
148
139
  end
149
- }
140
+ end
150
141
 
151
142
  raise FactoryError, "Couldn't find factory base for #{self.name}" if
152
143
  base.nil?
@@ -172,11 +163,12 @@ module PluginFactory
172
163
  keys << subclass.name.sub( /.*::/, '' ).downcase
173
164
  end
174
165
 
175
- keys.uniq.each {|key|
176
- #PluginFactory::log :info, "Registering %s derivative of %s as %p" %
177
- # [ subclass.name, self.name, key ]
166
+ keys.uniq.each do |key|
167
+ PluginFactory.log :info, "Registering %s derivative of %s as %p" %
168
+ [ subclass.name, self.name, key ]
178
169
  self.derivatives[ key ] = subclass
179
- }
170
+ end
171
+
180
172
  super
181
173
  end
182
174
 
@@ -188,56 +180,57 @@ module PluginFactory
188
180
  alias_method :derivativeClasses, :derivative_classes
189
181
 
190
182
 
191
- ### Given the <tt>className</tt> of the class to instantiate, and other
183
+ ### Given the <tt>class_name</tt> of the class to instantiate, and other
192
184
  ### arguments bound for the constructor of the new object, this method
193
185
  ### loads the derivative class if it is not loaded already (raising a
194
186
  ### LoadError if an appropriately-named file cannot be found), and
195
- ### instantiates it with the given <tt>args</tt>. The <tt>className</tt>
187
+ ### instantiates it with the given <tt>args</tt>. The <tt>class_name</tt>
196
188
  ### may be the the fully qualified name of the class, the class object
197
189
  ### itself, or the unique part of the class name. The following examples
198
190
  ### would all try to load and instantiate a class called "FooListener"
199
191
  ### if Listener included Factory
200
- ### obj = Listener::create( 'FooListener' )
201
- ### obj = Listener::create( FooListener )
202
- ### obj = Listener::create( 'Foo' )
203
- def create( subType, *args, &block )
204
- subclass = get_subclass( subType )
205
-
206
- return subclass.new( *args, &block )
207
- rescue => err
208
- nicetrace = err.backtrace.reject {|frame| /#{__FILE__}/ =~ frame}
209
- msg = "When creating '#{subType}': " + err.message
210
- Kernel::raise( err.class, msg, nicetrace )
192
+ ### obj = Listener.create( 'FooListener' )
193
+ ### obj = Listener.create( FooListener )
194
+ ### obj = Listener.create( 'Foo' )
195
+ def create( class_name, *args, &block )
196
+ subclass = get_subclass( class_name )
197
+
198
+ begin
199
+ return subclass.new( *args, &block )
200
+ rescue => err
201
+ nicetrace = err.backtrace.reject {|frame| /#{__FILE__}/ =~ frame}
202
+ msg = "When creating '#{class_name}': " + err.message
203
+ Kernel.raise( err, msg, nicetrace )
204
+ end
211
205
  end
212
206
 
213
207
 
214
- ### Given a <tt>className</tt> like that of the first argument to
208
+ ### Given a <tt>class_name</tt> like that of the first argument to
215
209
  ### #create, attempt to load the corresponding class if it is not
216
210
  ### already loaded and return the class object.
217
- def get_subclass( className )
218
- return self if ( self.name == className || className == '' )
219
- return className if className.is_a?( Class ) && className >= self
211
+ def get_subclass( class_name )
212
+ return self if ( self.name == class_name || class_name == '' )
213
+ if class_name.is_a?( Class )
214
+ return class_name if class_name <= self
215
+ raise ArgumentError, "%s is not a descendent of %s" % [class_name, self]
216
+ end
220
217
 
221
- unless self.derivatives.has_key?( className.downcase )
222
- self.load_derivative( className )
218
+ class_name = class_name.to_s
223
219
 
224
- unless self.derivatives.has_key?( className.downcase )
225
- raise FactoryError,
226
- "load_derivative(%s) didn't add a '%s' key to the "\
227
- "registry for %s" %
228
- [ className, className.downcase, self.name ]
229
- end
220
+ # If the derivatives hash doesn't already contain the class, try to load it
221
+ unless self.derivatives.has_key?( class_name.downcase )
222
+ self.load_derivative( class_name )
230
223
 
231
- subclass = self.derivatives[ className.downcase ]
224
+ subclass = self.derivatives[ class_name.downcase ]
232
225
  unless subclass.is_a?( Class )
233
226
  raise FactoryError,
234
227
  "load_derivative(%s) added something other than a class "\
235
228
  "to the registry for %s: %p" %
236
- [ className, self.name, subclass ]
229
+ [ class_name, self.name, subclass ]
237
230
  end
238
231
  end
239
232
 
240
- return self.derivatives[ className.downcase ]
233
+ return self.derivatives[ class_name.downcase ]
241
234
  end
242
235
  alias_method :getSubclass, :get_subclass
243
236
 
@@ -251,42 +244,39 @@ module PluginFactory
251
244
  ### <tt>class.derivativeDirs</tt> returns <tt>['foo','bar']</tt> the
252
245
  ### require line is tried with both <tt>'foo/'</tt> and <tt>'bar/'</tt>
253
246
  ### prepended to it.
254
- def load_derivative( className )
255
- className = className.to_s
256
-
257
- #PluginFactory::log :debug, "Loading derivative #{className}"
247
+ def load_derivative( class_name )
248
+ PluginFactory.log :debug, "Loading derivative #{class_name}"
258
249
 
259
250
  # Get the unique part of the derived class name and try to
260
251
  # load it from one of the derivative subdirs, if there are
261
252
  # any.
262
- mod_name = self.get_module_name( className )
263
- self.require_derivative( mod_name )
253
+ mod_name = self.get_module_name( class_name )
254
+ result = self.require_derivative( mod_name )
264
255
 
265
256
  # Check to see if the specified listener is now loaded. If it
266
257
  # is not, raise an error to that effect.
267
- unless self.derivatives[ className.downcase ]
268
- raise FactoryError,
269
- "Couldn't find a %s named '%s'. Loaded derivatives are: %p" % [
258
+ unless self.derivatives[ class_name.downcase ]
259
+ errmsg = "Require of '%s' succeeded, but didn't load a %s named '%s' for some reason." % [
260
+ result,
270
261
  self.factory_type,
271
- className.downcase,
272
- self.derivatives.keys,
273
- ], caller(3)
262
+ class_name.downcase,
263
+ ]
264
+ PluginFactory.log :error, errmsg
265
+ raise FactoryError, errmsg, caller(3)
274
266
  end
275
-
276
- return true
277
267
  end
278
268
  alias_method :loadDerivative, :load_derivative
279
269
 
280
270
 
281
- ### Build and return the unique part of the given <tt>className</tt>
271
+ ### Build and return the unique part of the given <tt>class_name</tt>
282
272
  ### either by stripping leading namespaces if the name already has the
283
273
  ### name of the factory type in it (eg., 'My::FooService' for Service,
284
274
  ### or by appending the factory type if it doesn't.
285
- def get_module_name( className )
286
- if className =~ /\w+#{self.factory_type}/
287
- mod_name = className.sub( /(?:.*::)?(\w+)(?:#{self.factory_type})/, "\\1" )
275
+ def get_module_name( class_name )
276
+ if class_name =~ /\w+#{self.factory_type}/
277
+ mod_name = class_name.sub( /(?:.*::)?(\w+)(?:#{self.factory_type})/, "\\1" )
288
278
  else
289
- mod_name = className
279
+ mod_name = class_name
290
280
  end
291
281
 
292
282
  return mod_name
@@ -294,7 +284,7 @@ module PluginFactory
294
284
  alias_method :getModuleName, :get_module_name
295
285
 
296
286
 
297
- ### If the factory responds to the #derivativeDirs method, call
287
+ ### If the factory responds to the #derivative_dirs method, call
298
288
  ### it and use the returned array as a list of directories to
299
289
  ### search for the module with the specified <tt>mod_name</tt>.
300
290
  def require_derivative( mod_name )
@@ -313,48 +303,53 @@ module PluginFactory
313
303
  end
314
304
 
315
305
  subdirs = [ subdirs ] unless subdirs.is_a?( Array )
316
- PluginFactory::log :debug, "Subdirs are: %p" % [subdirs]
306
+ PluginFactory.log :debug, "Subdirs are: %p" % [subdirs]
317
307
  fatals = []
308
+ tries = []
318
309
 
319
310
  # Iterate over the subdirs until we successfully require a
320
311
  # module.
321
- catch( :found ) {
322
- subdirs.collect {|dir| dir.strip}.each do |subdir|
323
- self.make_require_path( mod_name, subdir ).each {|path|
324
- PluginFactory::log :debug, "Trying #{path}..."
325
-
326
- # Try to require the module, saving errors and jumping
327
- # out of the catch block on success.
328
- begin
329
- require( path.untaint )
330
- rescue LoadError => err
331
- PluginFactory::log :debug,
332
- "No module at '%s', trying the next alternative: '%s'" %
333
- [ path, err.message ]
334
- rescue ScriptError,StandardError => err
335
- fatals << err
336
- PluginFactory::log :error,
337
- "Found '#{path}', but encountered an error: %s\n\t%s" %
338
- [ err.message, err.backtrace.join("\n\t") ]
339
- else
340
- #PluginFactory::log :debug,
341
- # "Found '#{path}'. Throwing :found"
342
- throw :found
343
- end
344
- }
312
+ subdirs.collect {|dir| dir.strip}.each do |subdir|
313
+ self.make_require_path( mod_name, subdir ).each do |path|
314
+ PluginFactory.log :debug, "Trying #{path}..."
315
+ tries << path
316
+
317
+ # Try to require the module, saving errors and jumping
318
+ # out of the catch block on success.
319
+ begin
320
+ require( path.untaint )
321
+ rescue LoadError => err
322
+ PluginFactory.log :debug,
323
+ "No module at '%s', trying the next alternative: '%s'" %
324
+ [ path, err.message ]
325
+ rescue Exception => err
326
+ fatals << err
327
+ PluginFactory.log :error,
328
+ "Found '#{path}', but encountered an error: %s\n\t%s" %
329
+ [ err.message, err.backtrace.join("\n\t") ]
330
+ else
331
+ PluginFactory.log :info, "Loaded '#{path}' without error."
332
+ return path
333
+ end
345
334
  end
335
+ end
346
336
 
347
- #PluginFactory::log :debug, "fatals = %p" % [ fatals ]
348
-
349
- # Re-raise is there was a file found, but it didn't load for
350
- # some reason.
351
- if ! fatals.empty?
352
- #PluginFactory::log :debug, "Re-raising first fatal error"
353
- Kernel::raise( fatals.first )
354
- end
337
+ PluginFactory.log :debug, "fatals = %p" % [ fatals ]
355
338
 
356
- nil
357
- }
339
+ # Re-raise is there was a file found, but it didn't load for
340
+ # some reason.
341
+ if fatals.empty?
342
+ errmsg = "Couldn't find a %s named '%s': tried %p" % [
343
+ self.factory_type,
344
+ mod_name,
345
+ tries
346
+ ]
347
+ PluginFactory.log :error, errmsg
348
+ raise FactoryError, errmsg
349
+ else
350
+ PluginFactory.log :debug, "Re-raising first fatal error"
351
+ Kernel.raise( fatals.first )
352
+ end
358
353
  end
359
354
  alias_method :requireDerivative, :require_derivative
360
355
 
@@ -371,17 +366,20 @@ module PluginFactory
371
366
  # Make permutations of the two parts
372
367
  path << modname
373
368
  path << modname.downcase
374
- path << modname + myname
375
- path << modname.downcase + myname
376
- path << modname.downcase + myname.downcase
369
+ path << modname + myname
370
+ path << modname.downcase + myname
371
+ path << modname.downcase + myname.downcase
372
+ path << modname + '_' + myname
373
+ path << modname.downcase + '_' + myname
374
+ path << modname.downcase + '_' + myname.downcase
377
375
 
378
376
  # If a non-empty subdir was given, prepend it to all the items in the
379
377
  # path
380
378
  unless subdir.nil? or subdir.empty?
381
- path.collect! {|m| File::join(subdir, m)}
379
+ path.collect! {|m| File.join(subdir, m)}
382
380
  end
383
381
 
384
- PluginFactory::log :debug, "Path is: #{path.uniq.reverse.inspect}..."
382
+ PluginFactory.log :debug, "Path is: #{path.uniq.reverse.inspect}..."
385
383
  return path.uniq.reverse
386
384
  end
387
385
  alias_method :makeRequirePath, :make_require_path