logjam 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,13 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # Copyright (c), 2015 Peter Wood
4
+ # See the license.txt for details of the licensing of the code in this file.
5
+
6
+ module LogJam
7
+ class Configuration < Configurative::Settings
8
+ sources *(Dir.glob(File.join(Dir.getwd, "logging.{yml,yaml,json}")) +
9
+ Dir.glob(File.join(Dir.getwd, "config", "logging.{yml,yaml,json}")) +
10
+ Dir.glob(File.join(Dir.getwd, "**", "application.{yml,yaml,json}")))
11
+ section "logging"
12
+ end
13
+ end
@@ -7,34 +7,17 @@ require 'stringio'
7
7
 
8
8
  module LogJam
9
9
  # This class provides the exception class used by the LogJam library.
10
- class LogJamError < StandardError
11
- # Attribute accessor/mutator declarations.
12
- attr_accessor :verbose
13
-
14
- # Constructor for the LogJamError class.
10
+ class Error < StandardError
11
+ # Constructor for the LogJam::Error class.
15
12
  #
16
13
  # ==== Parameters
17
14
  # message:: The message to be associated with the error.
18
15
  # cause:: Any underlying exception to be associated with the error.
19
16
  # Defaults to nil.
20
- def initialize(message, cause=nil, verbose=true)
17
+ def initialize(message, cause=nil)
21
18
  super(message)
22
- @cause = cause
23
- @verbose = verbose
24
- end
25
-
26
- # This method fetches a stringified interpretation of an exception.
27
- def to_s()
28
- text = StringIO.new
29
- text << super
30
- if @verbose
31
- text << "\n" + self.backtrace.join("\n")
32
- if !@cause.nil?
33
- text << "\n\nCause: #{@cause}"
34
- text << "\n" + @cause.backtrace.join("\n")
35
- end
36
- end
37
- text.string
19
+ @cause = cause
38
20
  end
21
+ attr_reader :cause
39
22
  end
40
- end
23
+ end
@@ -0,0 +1,62 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # Copyright (c), 2012 Peter Wood
4
+ # See the license.txt for details of the licensing of the code in this file.
5
+
6
+ module LogJam
7
+ # This class represents a specialization of the Ruby Logger class. The class
8
+ # retains a Ruby Logger instance within itself and delegates all standard
9
+ # logger calls to this instance. This allows for changes to the underlying
10
+ # logger without changing the containing one, thus bypassing people caching
11
+ # an instance.
12
+ class Logger < ::Logger
13
+ extend Forwardable
14
+ def_delegators :@log, :add, :close, :datetime_format, :datetime_format=,
15
+ :debug, :debug?, :error, :error?, :fatal, :fatal?,
16
+ :formatter, :formatter=, :info, :info?, :level,
17
+ :level=, :progname, :progname=, :sev_threshold,
18
+ :sev_threshold=, :unknown, :warn, :warn?
19
+
20
+ # Constructor for the Logger class. All parameters are passed
21
+ # straight through to create a standard Ruby Logger instance except
22
+ # when the first parameter is a Logger instance. In this case the
23
+ # Logger passed in is used rather than creating a new one.
24
+ #
25
+ # ==== Parameters
26
+ # logdev:: The log device to be used by the logger. This should be
27
+ # be a String containing a file path/name, an IO object that
28
+ # the logging details will be written to or another logger
29
+ # that you want to wrap.
30
+ # shift_age:: The maximum number of old log files to retain or a String
31
+ # containing the rotation frequency for the log.
32
+ # shift_size:: The maximum size that the logging output will be allowed
33
+ # to grow to before rotation occurs.
34
+ def initialize(logdev, shift_age=0, shift_size=1048576)
35
+ @log = (logdev.kind_of?(::Logger) ? logdev : ::Logger.new(logdev, shift_age, shift_size))
36
+ @name = nil
37
+ end
38
+
39
+ # Attribute accessor/mutator declaration.
40
+ attr_accessor :name
41
+
42
+ # This method fetches the standard Ruby Logger instance contained within
43
+ # a Logger object.
44
+ def logger
45
+ @log
46
+ end
47
+
48
+ # This method updates the logger instance contained within a Logger
49
+ # object.
50
+ #
51
+ # ==== Parameters
52
+ # logger:: The object to set as the contained logger. This should be an
53
+ # instance of the standard Ruby Logger class or something
54
+ # compatible with this.
55
+ def logger=(logger)
56
+ @log = logger
57
+ end
58
+
59
+ # Aliases
60
+ alias :log :add
61
+ end
62
+ end
data/lib/logjam/object.rb CHANGED
@@ -4,30 +4,30 @@
4
4
  # See the license.txt for details of the licensing of the code in this file.
5
5
 
6
6
  class Object
7
- # This method provides an instance level accessor to obtain a logger. Unless
8
- # a name is specified the logger returned is the default one.
9
- def log
10
- LogJam.get_logger
11
- end
7
+ # This method provides an instance level accessor to obtain a logger. Unless
8
+ # a name is specified the logger returned is the default one.
9
+ def log
10
+ LogJam.get_logger
11
+ end
12
12
 
13
- # This method provides a class level accessor to obtain a logger. Unless a
14
- # name is specified the logger returned is the default one.
15
- def self.log
16
- LogJam.get_logger
17
- end
13
+ # This method provides a class level accessor to obtain a logger. Unless a
14
+ # name is specified the logger returned is the default one.
15
+ def self.log
16
+ LogJam.get_logger
17
+ end
18
18
 
19
- def self.log=(logger)
20
- LogJam.get_logger.logger = logger
21
- end
19
+ def self.log=(logger)
20
+ LogJam.get_logger.logger = logger
21
+ end
22
22
 
23
- # This method allows a class to specify the name of the logger that it uses
24
- # once, generally within the class definition.
25
- #
26
- # ==== Parameters
27
- # name:: The name of the logger used by the class.
28
- # context:: A Hash of additional parameters that are specific to the class
29
- # to which LogJam is being applied.
30
- def self.set_logger_name(name, context={})
31
- LogJam.apply(self, name, context)
32
- end
33
- end
23
+ # This method allows a class to specify the name of the logger that it uses
24
+ # once, generally within the class definition.
25
+ #
26
+ # ==== Parameters
27
+ # name:: The name of the logger used by the class.
28
+ # context:: A Hash of additional parameters that are specific to the class
29
+ # to which LogJam is being applied.
30
+ def self.set_logger_name(name, context={})
31
+ LogJam.apply(self, name, context)
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module LogJam
2
- VERSION="1.1.0"
3
- end
2
+ VERSION="1.2.0"
3
+ end
metadata CHANGED
@@ -1,32 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logjam
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
5
- prerelease:
4
+ version: 1.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Black North
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-11-12 00:00:00.000000000 Z
11
+ date: 2015-07-25 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.3'
14
27
  - !ruby/object:Gem::Dependency
15
28
  name: json
16
29
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
30
  requirements:
19
- - - ! '>='
31
+ - - "~>"
20
32
  - !ruby/object:Gem::Version
21
- version: '0'
33
+ version: '1.8'
22
34
  type: :runtime
23
35
  prerelease: false
24
36
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
37
  requirements:
27
- - - ! '>='
38
+ - - "~>"
28
39
  - !ruby/object:Gem::Version
29
- version: '0'
40
+ version: '1.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: configurative
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.0'
30
55
  description: LogJam is a library to simplify the use of logging across libraries and
31
56
  applications.
32
57
  email: ruby@blacknorth.com
@@ -34,37 +59,36 @@ executables: []
34
59
  extensions: []
35
60
  extra_rdoc_files: []
36
61
  files:
37
- - lib/logjam/version.rb
38
- - lib/logjam/logjam.rb
62
+ - README.md
63
+ - lib/logjam.rb
64
+ - lib/logjam/configuration.rb
39
65
  - lib/logjam/exceptions.rb
40
- - lib/logjam/logjam_logger.rb
66
+ - lib/logjam/logger.rb
41
67
  - lib/logjam/object.rb
42
- - lib/logjam/logjam_logger2.rb
43
- - lib/logjam.rb
68
+ - lib/logjam/version.rb
44
69
  - license.txt
45
- - README
46
70
  homepage: https://github.com/free-beer/LogJam
47
- licenses: []
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
48
74
  post_install_message:
49
75
  rdoc_options: []
50
76
  require_paths:
51
77
  - lib
52
78
  required_ruby_version: !ruby/object:Gem::Requirement
53
- none: false
54
79
  requirements:
55
- - - ! '>='
80
+ - - ">="
56
81
  - !ruby/object:Gem::Version
57
82
  version: '0'
58
83
  required_rubygems_version: !ruby/object:Gem::Requirement
59
- none: false
60
84
  requirements:
61
- - - ! '>='
85
+ - - ">="
62
86
  - !ruby/object:Gem::Version
63
87
  version: '0'
64
88
  requirements: []
65
89
  rubyforge_project:
66
- rubygems_version: 1.8.25
90
+ rubygems_version: 2.4.5
67
91
  signing_key:
68
- specification_version: 3
92
+ specification_version: 4
69
93
  summary: A library to aggregate logging.
70
94
  test_files: []
data/lib/logjam/logjam.rb DELETED
@@ -1,395 +0,0 @@
1
- #! /usr/bin/env ruby
2
- #
3
- # Copyright (c), 2012 Peter Wood
4
- # See the license.txt for details of the licensing of the code in this file.
5
-
6
- require 'json'
7
- require 'logger'
8
- require 'stringio'
9
- require 'yaml'
10
-
11
- # This module defines the name space to be used by all code within the
12
- # LogJam library.
13
- module LogJam
14
- # Module constants.
15
- LOGGER_NAME = :name
16
- LOGGER_FILE = :file
17
- LOGGER_ROTATION = :rotation
18
- LOGGER_MAX_SIZE = :max_size
19
- LOGGER_LEVEL = :level
20
- LOGGER_DEFAULT = :default
21
- LOGGER_DATETIME_FORMAT = :datetime_format
22
- DEFAULT_FILE_NAMES = [".#{File::SEPARATOR}logging.yaml",
23
- ".#{File::SEPARATOR}logging.yml",
24
- ".#{File::SEPARATOR}logging.json",
25
- ".#{File::SEPARATOR}config#{File::SEPARATOR}logging.yaml",
26
- ".#{File::SEPARATOR}config#{File::SEPARATOR}logging.yml",
27
- ".#{File::SEPARATOR}config#{File::SEPARATOR}logging.json"]
28
-
29
- # Module static properties.
30
- @@logjam_modules = {}
31
- @@logjam_loggers = {}
32
- @@logjam_contexts = {}
33
-
34
- # This method is used to configure the LogJam module with the various loggers
35
- # it will use.
36
- #
37
- # ==== Parameters
38
- # source:: Either a String containing the path and name of the configuration
39
- # file containing the logging set up, an IO object from which the
40
- # configuration details can be read, a Hash containing a logging
41
- # configuration or nil.
42
- def self.configure(source)
43
- @@logjam_modules = {}
44
- @@logjam_loggers = {}
45
-
46
- # Check for default files if nil was passed in.
47
- source = LogJam.find_default_file if source.nil?
48
-
49
- if !source.kind_of?(Hash) && !source.nil?
50
- io = source.kind_of?(String) ? File.new(source) : source
51
- type = source.kind_of?(String) ? LogJam.guess_format(source) : nil
52
- LogJam.process_configuration(LogJam.load_configuration(io, type))
53
- elsif source.nil?
54
- LogJam.process_configuration({})
55
- else
56
- LogJam.process_configuration(source)
57
- end
58
- end
59
-
60
- # This method is used to install logging facilities at the class level for a
61
- # given class. Once 'logified' a class will possess two new methods. The
62
- # first, #log(), retrieves the logger associated with the class. The second,
63
- # #log=(), allows the assignment of the logger associated with the class.
64
- # Note that changing the logger associated with a class will impact all other
65
- # classes that use the same logger.
66
- #
67
- # ==== Parameters
68
- # target:: The target class that is to be extended.
69
- # name:: The name of the logger to be used by the class. Defaults to nil
70
- # to indicate use of the default logger.
71
- # context:: A Hash of additional parameters that are specific to the class
72
- # to which LogJam is being applied.
73
- def self.apply(target, name=nil, context={})
74
- @@logjam_contexts[target] = {}.merge(context)
75
- target.extend(LogJam.get_module(name, @@logjam_contexts[target]))
76
- target.send(:define_method, :log) {LogJam.get_logger(name)} if !target.method_defined?(:log)
77
- end
78
-
79
- # This method attempts to fetch the logger for a specified name. If this
80
- # logger does not exist then a default logger will be returned instead.
81
- #
82
- # ==== Parameters
83
- # name:: The name of the logger to retrieve.
84
- def self.get_logger(name=nil)
85
- LogJam.process_configuration(nil) if @@logjam_loggers.empty?
86
- @@logjam_loggers.fetch(name, @@logjam_loggers[nil])
87
- end
88
-
89
- # This method fetches a list of the names currently defined within the LogJam
90
- # internal settings.
91
- def self.names
92
- @@logjam_loggers.keys.compact
93
- end
94
-
95
- # A convenience mechanism that provides an instance level access to the
96
- # class level logger.
97
- def log
98
- self.class.log
99
- end
100
-
101
- private
102
-
103
- # This method fetches the module associated with a name. If the module does
104
- # not exist the default module is returned instead.
105
- #
106
- # ==== Parameters
107
- # name:: The name associated with the module to return.
108
- # context:: The context that applies to the module to be retrieved.
109
- def self.get_module(name, context={})
110
- LogJam.create_module(name)
111
- end
112
-
113
- # This method attempts to load a LogJam configuration from an IO object.
114
- #
115
- # ==== Parameters
116
- # source:: The IO object to read the configuration details from.
117
- # type:: An indicator of the format being used for the configuration. This
118
- # should be :yaml, :json or nil. Nil indicates that the library
119
- # will try to load the file in various formats.
120
- def self.load_configuration(source, type)
121
- configuration = nil
122
- if ![:yaml, :json].include?(type)
123
- begin
124
- # Read in the full details of the configuration.
125
- details = source.read
126
-
127
- # Try YAML format first.
128
- begin
129
- configuration = LogJam.load_yaml_configuration(StringIO.new(details))
130
- rescue LogJamError
131
- # Assume wrong format and ignore.
132
- configuration = nil
133
- end
134
-
135
- if configuration.nil?
136
- # Try JSON format second.
137
- begin
138
- configuration = LogJam.load_json_configuration(StringIO.new(details))
139
- rescue LogJamError
140
- # Assume wrong format and ignore.
141
- configuration = nil
142
- end
143
- end
144
- rescue => error
145
- raise LogJamError.new("Exception raised loading the LogJam "\
146
- "configuration.\nCause: #{error}", error)
147
- end
148
-
149
- # Check if the load was successful.
150
- if configuration.nil?
151
- raise LogJamError.new("Error loading the LogJam configuration. The "\
152
- "configuration is not in a recognised format "\
153
- "or contains errors. The configuration must "\
154
- "be in either YAML or JSON format.")
155
- end
156
- elsif type == :json
157
- configuration = LogJam.load_json_configuration(source)
158
- elsif type == :yaml
159
- configuration = LogJam.load_yaml_configuration(source)
160
- end
161
- configuration
162
- end
163
-
164
- # This method attempts to load a configuration for the LogJam library from
165
- # a file. The configuration is expected to be in YAML format.
166
- #
167
- # ==== Parameters
168
- # source:: An IO object from which the configuration will be read.
169
- def self.load_yaml_configuration(source)
170
- begin
171
- YAML.load(source)
172
- rescue => error
173
- raise LogJamError.new("Error loading LogJam configuration from YAML "\
174
- "source.\nCause: #{error}", error)
175
- end
176
- end
177
-
178
- # This method attempts to load a configuration for the LogJam library from
179
- # a file. The configuration is expected to be in JSON format.
180
- #
181
- # ==== Parameters
182
- # source:: An IO object from which the configuration will be read.
183
- def self.load_json_configuration(source)
184
- begin
185
- JSON.parse(source.read)
186
- rescue => error
187
- raise LogJamError.new("Error loading LogJam configuration from JSON "\
188
- "source.\nCause: #{error}", error)
189
- end
190
- end
191
-
192
- # This method processes a logger configuration and generates the appropriate
193
- # set of loggers and internal objects from it.
194
- #
195
- # ==== Parameters
196
- # configuration:: The configuration to be processed. If this is nil or empty
197
- # then a single default logger is generated that writes to the standard
198
- # output stream.
199
- def self.process_configuration(configuration)
200
- if !configuration.nil? && !configuration.empty?
201
- key = (configuration.include?(:loggers) ? :loggers : "loggers")
202
- if configuration.include?(key)
203
- loggers = configuration[key]
204
- if loggers.kind_of?(Array)
205
- configuration[key].each do |definition|
206
- LogJam.create_logger(definition)
207
- end
208
- elsif loggers.kind_of?(Hash)
209
- LogJam.create_logger(loggers)
210
- else
211
- raise LogJamError.new("The loggers configuration entry is in "\
212
- "an unrecognised format. Must be either "\
213
- "a Hash or an Array.")
214
- end
215
- end
216
- end
217
-
218
- # Set up any aliases that have been specified.
219
- if !@@logjam_loggers.empty? && !configuration.nil? && !configuration.empty?
220
- key = (configuration.include?(:loggers) ? :aliases : "aliases")
221
- if configuration.include?(key)
222
- configuration[key].each do |name, equivalent|
223
- @@logjam_loggers[name] = LogJam.get_logger(equivalent)
224
- @@logjam_modules[name] = LogJam.get_module(equivalent)
225
- end
226
- end
227
- end
228
-
229
- # Create a default logger if one hasn't been specified.
230
- if @@logjam_loggers[nil].nil?
231
- LogJam.create_logger({LOGGER_FILE => "STDOUT"})
232
- end
233
- end
234
-
235
- # This method is used to create an anonymous module under a given name (if it
236
- # doesn't already exist) and return it to the caller.
237
- #
238
- # ==== Parameters
239
- # name:: The name to create the module under.
240
- def self.create_module(name)
241
- if !@@logjam_modules.include?(name)
242
- # Create the anonymous module and add methods to it.
243
- @@logjam_modules[name] = Module.new
244
- @@logjam_modules[name].send(:define_method, :log) do
245
- LogJam.get_logger(name)
246
- end
247
- @@logjam_modules[name].send(:define_method, :log=) do |logger|
248
- LogJam.get_logger(name).logger = logger
249
- end
250
- end
251
- @@logjam_modules[name]
252
- end
253
-
254
- # This method extends a specified class with a named module.
255
- #
256
- # ==== Parameters
257
- # target:: The class that is to be extended.
258
- # name:: The name of the module to extend the class with.
259
- def self.extend_class(target, name)
260
- target.extend(LogJam.get_module(name))
261
- end
262
-
263
- # This method attempts to guess the format that configuration details will be
264
- # in given a file name. Guessing is done by looking at the file's extension.
265
- # Files ending in '.yaml' or '.yml' are considered YAML. Files ending '.json'
266
- # are considered JSON. The method returns nil if the path passed in has
267
- # neither of these extensions.
268
- #
269
- # ==== Parameters
270
- # path:: The path and name of the file to make the guess from.
271
- def self.guess_format(path)
272
- type = nil
273
- if path.nil? && path.include?(".")
274
- offset = path.length - path.reverse.index(".")
275
- extension = path[offset, path.length - offset].downcase
276
- case extension
277
- when 'yaml', 'yml'
278
- type = :yaml
279
-
280
- when 'json'
281
- type = :json
282
- end
283
- end
284
- type
285
- end
286
-
287
- # This method creates a logger from a given definition. A definition should
288
- # be a Hash containing the values that are used to configure the Logger with.
289
- #
290
- # ==== Parameters
291
- # definition:: A Hash containing the configuration details for the logger.
292
- def self.create_logger(definition)
293
- # Fetch the configuration values.
294
- name = LogJam.get_value(definition, LOGGER_NAME)
295
- path = LogJam.get_value(definition, LOGGER_FILE)
296
- rotation = LogJam.get_value(definition, LOGGER_ROTATION)
297
- max_size = LogJam.get_value(definition, LOGGER_MAX_SIZE)
298
- level = LogJam.get_value(definition, LOGGER_LEVEL)
299
- default = LogJam.get_value(definition, LOGGER_DEFAULT)
300
-
301
- device = nil
302
- if ["STDOUT", "STDERR"].include?(path)
303
- device = (path == "STDOUT" ? STDOUT : STDERR)
304
- else
305
- device = path
306
- end
307
-
308
- if rotation.kind_of?(String) && /^\s*\d+\s*$/ =~ rotation
309
- rotation = rotation.to_i
310
- rotation = 0 if rotation < 0
311
- end
312
-
313
- if !max_size.nil? && max_size.kind_of?(String)
314
- max_size = max_size.to_i
315
- end
316
- max_size = 1048576 if !max_size.nil? && max_size < 1024
317
-
318
- if !level.nil?
319
- case level.downcase
320
- when 'info'
321
- level = Logger::INFO
322
-
323
- when 'warn'
324
- level = Logger::WARN
325
-
326
- when 'error'
327
- level = Logger::ERROR
328
-
329
- when 'fatal'
330
- level = Logger::FATAL
331
-
332
- when 'unknown'
333
- level = Logger::UNKNOWN
334
-
335
- else
336
- level = Logger::DEBUG
337
- end
338
- else
339
- level = Logger::DEBUG
340
- end
341
-
342
- if default != true
343
- if default.kind_of?(String)
344
- default = ["true", "yes", "on", "1"].include?(default.downcase)
345
- else
346
- default = false
347
- end
348
- end
349
-
350
- # Create the actual logger and associated module.
351
- logger = LogJamLogger.new(device, rotation, max_size)
352
- logger.level = level
353
- logger.name = name
354
- logger.progname = name
355
- @@logjam_loggers[name] = logger
356
- logger_module = LogJam.create_module(name)
357
- if default
358
- @@logjam_loggers[nil] = logger
359
- @@logjam_modules[nil] = logger_module
360
- end
361
- logger
362
- end
363
-
364
- # This method attempts to fetch a value from a Hash. The key passed to the
365
- # method should be a symbol and this will be checked for first. If this is
366
- # not found then a check is made for the string equivalent. The first of
367
- # these that is present in the Hash generates the value returned. If neither
368
- # is present in the Hash then nil is returned.
369
- #
370
- # ==== Parameters
371
- # source:: The Hash that will be checked for the value.
372
- # key:: A symbol that will be checked as the key for the value.
373
- def self.get_value(source, key)
374
- if source.include?(key)
375
- source[key]
376
- elsif source.include?(key.to_s)
377
- source[key.to_s]
378
- else
379
- nil
380
- end
381
- end
382
-
383
- # This module level method is used to check for the existence of a
384
- # configuration file under one or a standard set of names. This method is
385
- # only used whenever the configure method is called and either passed nil
386
- # or no parameter.
387
- def self.find_default_file
388
- file_name = nil
389
- DEFAULT_FILE_NAMES.each do |name|
390
- file_name = name if File.exists?(name) && File.readable?(name)
391
- break if !file_name.nil?
392
- end
393
- file_name
394
- end
395
- end