libis-tools 0.9.20 → 0.9.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +36 -233
- data/Rakefile +5 -0
- data/lib/libis/tools.rb +1 -0
- data/lib/libis/tools/assert.rb +11 -0
- data/lib/libis/tools/checksum.rb +22 -5
- data/lib/libis/tools/command.rb +24 -3
- data/lib/libis/tools/config.rb +61 -33
- data/lib/libis/tools/config_file.rb +0 -1
- data/lib/libis/tools/deep_struct.rb +10 -2
- data/lib/libis/tools/extend/empty.rb +2 -2
- data/lib/libis/tools/extend/hash.rb +37 -18
- data/lib/libis/tools/extend/kernel.rb +9 -0
- data/lib/libis/tools/extend/string.rb +17 -8
- data/lib/libis/tools/logger.rb +95 -44
- data/lib/libis/tools/metadata.rb +5 -1
- data/lib/libis/tools/metadata/dublin_core_record.rb +22 -4
- data/lib/libis/tools/metadata/field_format.rb +49 -9
- data/lib/libis/tools/metadata/fix_field.rb +5 -0
- data/lib/libis/tools/metadata/mapper.rb +2 -1
- data/lib/libis/tools/metadata/mappers/flandrica.rb +8 -1
- data/lib/libis/tools/metadata/mappers/kuleuven.rb +6 -2
- data/lib/libis/tools/metadata/marc21_record.rb +1 -0
- data/lib/libis/tools/metadata/marc_record.rb +31 -12
- data/lib/libis/tools/metadata/parser/basic_parser.rb +2 -0
- data/lib/libis/tools/metadata/parser/dublin_core_parser.rb +2 -1
- data/lib/libis/tools/metadata/parser/marc21_parser.rb +2 -1
- data/lib/libis/tools/metadata/parser/marc_format_parser.rb +2 -1
- data/lib/libis/tools/metadata/parser/marc_rules.rb +2 -1
- data/lib/libis/tools/metadata/parser/marc_select_parser.rb +2 -1
- data/lib/libis/tools/metadata/parser/patch.rb +1 -0
- data/lib/libis/tools/metadata/parser/subfield_criteria_parser.rb +2 -1
- data/lib/libis/tools/metadata/sharepoint_mapping.rb +1 -0
- data/lib/libis/tools/metadata/sharepoint_record.rb +2 -0
- data/lib/libis/tools/metadata/var_field.rb +8 -0
- data/lib/libis/tools/mets_dnx.rb +61 -0
- data/lib/libis/tools/mets_file.rb +87 -604
- data/lib/libis/tools/mets_objects.rb +534 -0
- data/lib/libis/tools/parameter.rb +144 -21
- data/lib/libis/tools/thread_safe.rb +31 -0
- data/lib/libis/tools/version.rb +1 -1
- data/lib/libis/tools/xml_document.rb +18 -24
- data/libis-tools.gemspec +6 -2
- data/spec/config_spec.rb +3 -4
- data/spec/logger_spec.rb +13 -30
- data/spec/mets_file_spec.rb +17 -17
- metadata +53 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc18f91c7fdaf317168eb91966d598fff6fd0252
|
4
|
+
data.tar.gz: 43d8f7c0f51f7e5e32b28680f53bb6f6dbb17658
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db2e5d1f92574eaefab41674b23aac4aa116b01206eb5eeb1304482de6dba8213a00b3c3ccfd79a83be1523b7d947d07112dd445ddadfeb781176f0fefacf65d
|
7
|
+
data.tar.gz: 5983fc775104c2d592fdeacdec3c86489215275ab9f138bf72211696e049e21f093e2f25e197a722d854962753652c469972e22a4dd123af58b9dd951ce8b782
|
data/README.md
CHANGED
@@ -42,181 +42,64 @@ sections below for their names.
|
|
42
42
|
|
43
43
|
## Content
|
44
44
|
|
45
|
-
### assert
|
45
|
+
### {Object#assert}
|
46
46
|
|
47
|
-
The Object#assert method enables the assert functionality found in other languages.
|
48
|
-
|
49
|
-
If the boolean expression evaluates to false an AssertionFailure exception will be raised.
|
47
|
+
The {Object#assert} method enables the assert functionality found in other languages. Since it is defined on the
|
48
|
+
Object class, it is available on almost any class.
|
50
49
|
|
51
|
-
|
52
|
-
exception will be raised. In that case the first argument passed to the assert method is used as message and the second
|
53
|
-
argument is ignored.
|
50
|
+
### {::Libis::Tools::Checksum}
|
54
51
|
|
55
|
-
The
|
56
|
-
|
57
|
-
on.
|
52
|
+
The {::Libis::Tools::Checksum} class offers a standardized interface for calculating checksums of file
|
53
|
+
contents in different formats.
|
58
54
|
|
59
|
-
|
55
|
+
### {::Libis::Tools::Command}
|
60
56
|
|
61
|
-
|
62
|
-
|
63
|
-
assert(value > 0, 'value should be positive number')
|
64
|
-
```
|
65
|
-
and using a code block:
|
66
|
-
|
67
|
-
```ruby
|
68
|
-
require 'libis/tools/assert'
|
69
|
-
assert 'database is not idle' do
|
70
|
-
db = get_database
|
71
|
-
db.status == :IDLE
|
72
|
-
end
|
73
|
-
```
|
74
|
-
|
75
|
-
### Checksum
|
57
|
+
The {::Libis::Tools::Command} module offers a safe way to execute external commands and gives you access to the
|
58
|
+
exit status as well as standard output and standard error information. May have issues on older JRuby versions.
|
76
59
|
|
77
|
-
|
78
|
-
different formats. The actual list of supported checksum formats is in ::Libis::Tools::Checksum.CHECKSUM_TYPES. It
|
79
|
-
contains MD5, SHA-1 and SHA-2 (in 256-bit, 384-bit and 512-bit variants).
|
80
|
-
|
81
|
-
There are two ways this can be used: using a class instance or using class methods. When a class instance is used, the
|
82
|
-
desired checksum type has to be supplied when the instance is created. Each call to a checksum method will calculate the
|
83
|
-
checksum and reset the digest to prevent future calls to be affected by the current result. When a class method is used
|
84
|
-
besides the file name, the checksum type has to be supplied.
|
85
|
-
|
86
|
-
The available methods on both instance and class level are:
|
87
|
-
|
88
|
-
* digest: return the checksum as (binary) string.
|
89
|
-
* hexdigest: return the checksum as hexadecimal encoded string.
|
90
|
-
* base64digest: return the checksum as base64 encoded string.
|
91
|
-
|
92
|
-
Examples:
|
93
|
-
|
94
|
-
```ruby
|
95
|
-
require 'libis/tools/checksum'
|
96
|
-
checksum = ::Libis::Tools::Checksum.new(:MD5)
|
97
|
-
puts "Checksum: #{checksum.hexdigest(file_name)} (MD5, hex)"
|
98
|
-
```
|
99
|
-
|
100
|
-
```ruby
|
101
|
-
require 'libis/tools/checksum'
|
102
|
-
puts "Checksum: #{::Libis::Tools::Checksum.base64digest(file_name, :SHA384)} (SHA-2, 384 bit, base64)"
|
103
|
-
```
|
104
|
-
|
105
|
-
### Command
|
106
|
-
|
107
|
-
This module allows to run an external command safely and returns it's output, error messages and status. The run method
|
108
|
-
takes any number of arguments that will be used as command-line arguments. The method returns a Hash with:
|
109
|
-
|
110
|
-
* :out => an array with lines that were printed on the external program's standard out.
|
111
|
-
* :err => an array with lines that were printed on the external program's standard error.
|
112
|
-
* :status => exit code returned by the external program.
|
113
|
-
|
114
|
-
```ruby
|
115
|
-
require 'libis/tools/command'
|
116
|
-
result = ::Libis::Tools::Command.run('ls', '-l', File.absolute_path(__FILE__))
|
117
|
-
p result # => {out: [...], err: [...], status: 0}
|
118
|
-
```
|
119
|
-
|
120
|
-
or:
|
121
|
-
|
122
|
-
```ruby
|
123
|
-
require 'libis/tools/command'
|
124
|
-
include ::Libis::Tools::Command
|
125
|
-
result = run('ls', '-l', File.absolute_path(__FILE__))
|
126
|
-
p result # => {out: [...], err: [...], status: 0}
|
127
|
-
```
|
60
|
+
### {::Libis::Tools::DeepStruct}
|
128
61
|
|
129
|
-
|
130
|
-
|
62
|
+
A class that derives from OpenStruct through the RecursiveOpenStruct.
|
63
|
+
By wrapping a Hash recursively, it allows for easy access to the content by method names.
|
131
64
|
|
132
|
-
###
|
65
|
+
### {::Libis::Tools::ConfigFile}
|
133
66
|
|
134
|
-
A class
|
135
|
-
|
67
|
+
A base class for {::Libis::Tools::Config}, but useable on it's own.
|
68
|
+
It extends the DeepStruct with loading from and saving to YAML files.
|
136
69
|
|
137
|
-
###
|
70
|
+
### {::Libis::Tools::Config}
|
138
71
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
```ruby
|
143
|
-
require 'libis/tools/config_file'
|
144
|
-
cfg_file = ::Libis::Tools::ConfigFile.new
|
145
|
-
cfg_file << {foo: 'bar'}
|
146
|
-
cfg_file.my_value = 10
|
147
|
-
p cfg_file[:my_value] # => 10
|
148
|
-
cfg_file{:my_text] = 'abc'
|
149
|
-
p cfg_file['my_text'] # => 'abc'
|
150
|
-
p cfg_file.to_hash # => { :foo => 'bar', 'my_value' => 10, :my_text => 'abc' }
|
151
|
-
cfg >> 'my_config.yml'
|
152
|
-
```
|
153
|
-
### Config
|
72
|
+
This Singleton class is a convenience class for easy configuration maintenance and loading.
|
73
|
+
It also initializes a default logger.
|
154
74
|
|
155
|
-
|
156
|
-
DeepStruc, it supports code defaults and loading configurations from multiple YAML files containing ERB statements.
|
157
|
-
The Config class follows the Singleton pattern and behaves like a Hash/OpenStruct/HashWithIndifferentAccess with
|
158
|
-
recursion over hashes and arrays. It also initializes a default Logger instance.
|
75
|
+
### {::Libis::Tools::Logger}
|
159
76
|
|
160
|
-
|
161
|
-
call or via the Hash operator using the parameter name either as a string or a symbol.
|
77
|
+
The ::Libis::Tools::Logger module adds support for logging functionality to any class.
|
162
78
|
|
163
|
-
|
79
|
+
## {::Libis::Tools::Metadata}
|
164
80
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
cfg << 'my_config.yml'
|
169
|
-
cfg['my_value'] = 10
|
170
|
-
p cfg.instance.my_value # => 10
|
171
|
-
cfg.instance.my_text = 'abc'
|
172
|
-
p cfg[:my_text] # => 'abc'
|
173
|
-
p cfg.logger.warn('message') # => W, [2015-03-16T12:51:01.180548 #28935] WARN -- : message
|
174
|
-
```
|
81
|
+
This gem also provides some modules and classes that assist in working with metadata. There are classes that allow to
|
82
|
+
create and/or read metadata for MARC(21), Dublin Core and SharePoint. These classes all live in the
|
83
|
+
Libis::Tools::Metadata namespace.
|
175
84
|
|
176
|
-
###
|
85
|
+
### MARC
|
177
86
|
|
178
|
-
The
|
179
|
-
|
180
|
-
|
181
|
-
supplied arguments appended.
|
87
|
+
The classes {::Libis::Tools::Metadata::MarcRecord} and it's child class {::Libis::Tools::Metadata::Marc21Record} are
|
88
|
+
mainly built for reading MARC(21) records. Most of the class logic is in the base class
|
89
|
+
{::Libis::Tools::Metadata::MarcRecord MarcRecord}, which is incomplete and should be considered an abstract class.
|
182
90
|
|
183
|
-
|
184
|
-
the
|
185
|
-
|
91
|
+
{::Libis::Tools::Metadata::Marc21Record Marc21Record} on the other hand only contains the logic to parse the XML data
|
92
|
+
into the internal structure. A {::Libis::Tools::Metadata::MarcRecord MarcRecord} is created by supplying it an XML node
|
93
|
+
(from Nokogiri or {::Libis::Tools::XmlDocument}) that contains child nodes with the MARC data of a single record.
|
186
94
|
|
187
|
-
|
188
|
-
evaluated and if true debug, info and warning messages will not be printed.
|
95
|
+
The code will strip namespaces from the input in order to greatly simplify working with the XML.
|
189
96
|
|
190
|
-
|
97
|
+
## {::Libis::Tools::Parameter} and {::Libis::Tools::ParameterContainer}
|
191
98
|
|
192
|
-
|
193
|
-
|
194
|
-
class TestLogger
|
195
|
-
include ::Libis::Tools::Logger
|
196
|
-
attr_accessor :options, name
|
197
|
-
def initialize
|
198
|
-
@options = {}
|
199
|
-
@name = nil
|
200
|
-
end
|
201
|
-
end
|
202
|
-
tl = TestLogger.new
|
203
|
-
tl.debug 'message'
|
204
|
-
tl.options[:quiet] = true
|
205
|
-
tl.warn 'message'
|
206
|
-
::Libis::Tools::Config.appname = 'TestApplication'
|
207
|
-
tl.error 'huge error: [%d] %s', 1000, 'Exit'
|
208
|
-
tl.name = 'TestClass'
|
209
|
-
tl.options[:quiet] = false
|
210
|
-
tl.info 'Running application: %s', ::Libis::Tools::Config.appname
|
211
|
-
```
|
212
|
-
produces:
|
213
|
-
<pre>
|
214
|
-
D, [...] DEBUG -- TestLogger: message
|
215
|
-
E, [...] ERROR -- TestApplication: huge error: [1000] Exit
|
216
|
-
I, [...] INFO -- TestClass: Running application TestApplication
|
217
|
-
</pre>
|
99
|
+
The class {::Libis::Tools::Parameter} and the {::Libis::Tools::ParameterContainer} module provide a simple framework for
|
100
|
+
instance variables that are type-safe and can easily be documented and provide defaults.
|
218
101
|
|
219
|
-
### XmlDocument
|
102
|
+
### {::Libis::Tools::XmlDocument}
|
220
103
|
|
221
104
|
Class that embodies most used features of Nokogiri, Nori and Gyoku in one convenience class. The Nokogiri document is
|
222
105
|
stored in the class variable 'document' and can be accessed and manipulated directly - if required. The class supports
|
@@ -300,87 +183,7 @@ produces:
|
|
300
183
|
<email>harry.potter@hogwarts.edu</email>
|
301
184
|
<email>hpotter@JKRowling.com</email>
|
302
185
|
</patron>
|
303
|
-
|
304
|
-
## Metadata
|
305
|
-
|
306
|
-
This gem also provides some modules and classes that assist in working with metadata. There are classes that allow to
|
307
|
-
create and/or read metadata for MARC(21), Dublin Core and SharePoint. These classes all live in the
|
308
|
-
Libis::Tools::Metadata namespace.
|
309
|
-
|
310
|
-
### MARC
|
311
|
-
|
312
|
-
The classes Libis::Tools::Metadata::MarcRecord and it's child class Libis::Tools::Metadata::Marc21Record are mainly
|
313
|
-
built for reading MARC(21) records. Most of the class logic is in the base class MarcRecord, which is incomplete and
|
314
|
-
should be considered an abstract class. Marc21Record on the other hand only contains the logic to parse the XML data
|
315
|
-
into the internal structure. A MarcRecord is created by supplying it an XML node (from Nokogiri or
|
316
|
-
Libis::Tools::XmlDocument) that contains child nodes with the MARC data of a single record. The code will strip
|
317
|
-
namespaces from the input in order to greatly simplify working with the XML.
|
318
|
-
|
319
|
-
## Parameter
|
320
|
-
|
321
|
-
The class ::Libis::Tools::Parameter and the ::Libis::Tools::ParameterContainer module provide a simple framework for
|
322
|
-
instance variables that are type-safe and can easily be documented and provide defaults.
|
323
186
|
|
324
|
-
To use these parameters a class should include the ::Libis::Tools::ParameterContainer module and add 'parameter'
|
325
|
-
statements to the body of the class definition. It takes only one mandatory argument which is a Hash. The first entry is
|
326
|
-
interpreted as '<name> => <default>'. The name for the parameter should be unique and the default value can be any value
|
327
|
-
of type TrueClass, FalseClass, String, Integer, Float, Date, Time, DateTime, Array, Hash or NilClass.
|
328
|
-
|
329
|
-
The second up to last Hash entries are optional properties for the parameter. These are:
|
330
|
-
|
331
|
-
* datatype: the type of values the parameter will accept. Valid values are:
|
332
|
-
|
333
|
-
* 'bool' or 'boolean'
|
334
|
-
* 'string'
|
335
|
-
* 'int'
|
336
|
-
* 'float'
|
337
|
-
* 'datetime'
|
338
|
-
* 'array'
|
339
|
-
* 'hash'
|
340
|
-
|
341
|
-
Any other value will raise a RuntimeError when the parameter is used. The value is case-insensitive and if not present,
|
342
|
-
the datatype will be derived from the default value with 'string' being the default for NilClass. In any case the
|
343
|
-
parameter will try its best to convert supplied values to the proper data type. For instance, an Integer parameter will
|
344
|
-
accept 3, 3.1415, '3' and Rational(10/3) as valid values and store them as the integer value 3. Likewise DateTime
|
345
|
-
parameters will try to interprete date and time strings.
|
346
|
-
|
347
|
-
* description: any descriptive text you want to add to clarify what this parameter is used for. Any tool can ask the
|
348
|
-
class for its parameters and - for instance - can use this property to provide help in a GUI when asking the user for
|
349
|
-
input.
|
350
|
-
|
351
|
-
* constraint: adds a validation condition to the parameter. The condition value can be:
|
352
|
-
|
353
|
-
* an array: only values that convert to a value in the list are considered valid.
|
354
|
-
* a range: only values that convert to a value in the given range are considered valid.
|
355
|
-
* a regular expression: only values that match the regular expression are considered valid.
|
356
|
-
* a string: only values that are '==' to the constraint are considered valid.
|
357
|
-
|
358
|
-
* frozen: if set to true, prevents the class instance to set the parameter to any value other than the default. Mostly
|
359
|
-
useful when a derived class needs a parameter in the parent class to be set to a specific value. Setting a value on
|
360
|
-
a frozen parameter with the 'parameter(name,value)' method throws a ::Libis::Tools::ParameterFrozenError. The '[]='
|
361
|
-
method silently ignores the exception. In any case the default value will not be changed.
|
362
|
-
|
363
|
-
* options: a hash with any additional properties that you want to associate to the parameter. Any key-value pair in this
|
364
|
-
hash is added to the retrievable properties of the parameter. Likewise any property defined, that is not in the list of
|
365
|
-
known properties is added to the options hash. In this aspect the ::Libis::Tools::Parameter class behaves much like an
|
366
|
-
OpenStruct even though it is implemented as a Struct.
|
367
|
-
|
368
|
-
Besides enabling the 'parameter' class method to define parameters, the ::Libis::Tools::ParameterContainer add the class
|
369
|
-
method 'parameters' that will return a Hash with parameter names as keys and their respective parameter definitions as
|
370
|
-
values. On each class instance the 'parameter' method is added and serves as both getter and setter for parameter values:
|
371
|
-
With only one argument (the parameter name) it returns the current value for the parameter, but the optional second
|
372
|
-
argument will cause the method to set the parameter value. If the parameter is not available or the given value is not
|
373
|
-
a valid value for the parameter, the method will return the special constant ::Libis::ParameterContainer::NO_VALUE. The
|
374
|
-
methods '[]' and '[]=' serve as aliases for the getter and setter calls.
|
375
|
-
|
376
|
-
Additionally two protected methods are available on the instance:
|
377
|
-
* 'parameters': returns the Hash that keeps track of the current parameter values for the instance.
|
378
|
-
* 'get_parameter_defintion': retrieves the parameter definition from the instance's class for the given parameter name.
|
379
|
-
|
380
|
-
Any class that derives from a class that included the ::Libis::Tools::ParameterContainer module will automatically
|
381
|
-
inherit all parameter definitions from all of it's base classes and can override any of these parameter definitions e.g.
|
382
|
-
to change the default values for the parameter.
|
383
|
-
|
384
187
|
## Contributing
|
385
188
|
|
386
189
|
1. Fork it ( https://github.com/Kris-LIBIS/LIBIS_Tools/fork )
|
data/Rakefile
CHANGED
data/lib/libis/tools.rb
CHANGED
@@ -12,6 +12,7 @@ module Libis
|
|
12
12
|
autoload :Logger, 'libis/tools/logger'
|
13
13
|
autoload :MetsFile, 'libis/tools/mets_file'
|
14
14
|
autoload :Parameter, 'libis/tools/parameter'
|
15
|
+
autoload :ThreadSafe, 'libis/tools/thread_safe'
|
15
16
|
autoload :XmlDocument, 'libis/tools/xml_document'
|
16
17
|
|
17
18
|
end
|
data/lib/libis/tools/assert.rb
CHANGED
@@ -19,6 +19,17 @@ class Object
|
|
19
19
|
#
|
20
20
|
# Examples:
|
21
21
|
#
|
22
|
+
# require 'libis/tools/assert'
|
23
|
+
# assert(value > 0, 'value should be positive number')
|
24
|
+
#
|
25
|
+
# # using a code block:
|
26
|
+
# require 'libis/tools/assert'
|
27
|
+
# assert 'database is not idle' do
|
28
|
+
# db = get_database
|
29
|
+
# db.status == :IDLE
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # using $DEBUG:
|
22
33
|
# $DEBUG = nil
|
23
34
|
# assert false, 'assert 1' # nothing happens
|
24
35
|
# $DEBUG = true
|
data/lib/libis/tools/checksum.rb
CHANGED
@@ -11,16 +11,33 @@ module Libis
|
|
11
11
|
# All methods are available on the class and on the instance. The instance has to be initialized with a checksum
|
12
12
|
# algorithm and therefore the instance methods do not have to specify the checksum type.
|
13
13
|
#
|
14
|
+
# There are two ways this can be used: using a class instance or using class methods. When a class instance is used,
|
15
|
+
# the desired checksum type has to be supplied when the instance is created. Each call to a checksum method will
|
16
|
+
# calculate the checksum and reset the digest to prevent future calls to be affected by the current result. When a
|
17
|
+
# class method is used besides the file name, the checksum type has to be supplied.
|
18
|
+
#
|
19
|
+
# Examples:
|
20
|
+
#
|
21
|
+
# require 'libis/tools/checksum'
|
22
|
+
# checksum = ::Libis::Tools::Checksum.new(:MD5)
|
23
|
+
# puts "Checksum: #{checksum.hexdigest(file_name)} (MD5, hex)"
|
24
|
+
#
|
25
|
+
# require 'libis/tools/checksum'
|
26
|
+
# puts "Checksum: #{::Libis::Tools::Checksum.base64digest(file_name, :SHA384)} (SHA-2, 384 bit, base64)"
|
14
27
|
class Checksum
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
28
|
+
# All supported checksum types
|
29
|
+
CHECKSUM_TYPES = [:MD5, :SHA1, :SHA256, :SHA384, :SHA512]
|
30
|
+
|
31
|
+
# @!visibility private
|
32
|
+
# noinspection RubyResolve
|
33
|
+
unless defined? JRUBY_VERSION
|
34
|
+
checksum_types = CHECKSUM_TYPES
|
35
|
+
checksum_types << :RMD160
|
19
36
|
end
|
20
37
|
|
21
38
|
# Create instance for a given checksum algorithm.
|
22
39
|
#
|
23
|
-
# @param [Symbol] type checksum algorithm; one of {
|
40
|
+
# @param [Symbol] type checksum algorithm; one of {CHECKSUM_TYPES}
|
24
41
|
def initialize(type)
|
25
42
|
@hasher = self.class.get_hasher(type)
|
26
43
|
end
|
data/lib/libis/tools/command.rb
CHANGED
@@ -4,6 +4,27 @@ require 'open3'
|
|
4
4
|
module Libis
|
5
5
|
module Tools
|
6
6
|
|
7
|
+
# This module allows to run an external command safely and returns it's output, error messages and status.
|
8
|
+
# The run method takes any number of arguments that will be used as command-line arguments. The method returns
|
9
|
+
# a Hash with:
|
10
|
+
# * :out => an array with lines that were printed on the external program's standard out.
|
11
|
+
# * :err => an array with lines that were printed on the external program's standard error.
|
12
|
+
# * :status => exit code returned by the external program.
|
13
|
+
#
|
14
|
+
# Examples:
|
15
|
+
#
|
16
|
+
# require 'libis/tools/command'
|
17
|
+
# result = ::Libis::Tools::Command.run('ls', '-l', File.absolute_path(__FILE__))
|
18
|
+
# p result # => {out: [...], err: [...], status: 0}
|
19
|
+
#
|
20
|
+
# require 'libis/tools/command'
|
21
|
+
# include ::Libis::Tools::Command
|
22
|
+
# result = run('ls', '-l', File.absolute_path(__FILE__))
|
23
|
+
# p result # => {out: [...], err: [...], status: 0}
|
24
|
+
#
|
25
|
+
# Note that the Command class uses Open3#popen3 internally. All arguments supplied to Command#run are passed to
|
26
|
+
# the popen3 call. Unfortunately some older JRuby versions have some known issues with popen3. Please use and
|
27
|
+
# test carefully in JRuby environments.
|
7
28
|
module Command
|
8
29
|
|
9
30
|
# Run an external program and return status, stdout and stderr.
|
@@ -12,9 +33,9 @@ module Libis
|
|
12
33
|
# @param [String] cmd program name
|
13
34
|
# @param [Array<String>] opts optional list of command line arguments
|
14
35
|
# @return [Hash] a Hash with:
|
15
|
-
# *
|
16
|
-
# *
|
17
|
-
# *
|
36
|
+
# * :status (Integer) - the exit status of the command
|
37
|
+
# * :out (Array<String>) - the stdout output of the command
|
38
|
+
# * :err (Array<String>)- the stderr output of the command
|
18
39
|
def self.run(cmd, *opts)
|
19
40
|
result = {
|
20
41
|
status: 999,
|
data/lib/libis/tools/config.rb
CHANGED
@@ -2,18 +2,19 @@
|
|
2
2
|
require 'singleton'
|
3
3
|
require 'yaml'
|
4
4
|
require 'erb'
|
5
|
-
require '
|
5
|
+
require 'logging'
|
6
6
|
|
7
|
-
|
7
|
+
require_relative 'config_file'
|
8
8
|
|
9
9
|
module Libis
|
10
10
|
module Tools
|
11
11
|
|
12
|
-
# The Config class is a convenience class for easy configuration maintenance, loading and saving.
|
13
|
-
# It
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
12
|
+
# The Singleton Config class is a convenience class for easy configuration maintenance, loading and saving.
|
13
|
+
# It also initializes a default logger and supports creating extra loggers. The logging infrastructure is based on
|
14
|
+
# the {http://www.rubydoc.info/gems/logging/Logging ::Logging} gem and supports the {::Libis::Tools::Logger} class.
|
15
|
+
#
|
16
|
+
# For the configuration parameters, it supports code defaults, loading configurations from multiple YAML files
|
17
|
+
# containing ERB statements. The Config class behaves like a Hash/OpenStruct/HashWithIndifferentAccess.
|
17
18
|
#
|
18
19
|
# The parameters can be accessed by getter/setter method or using the Hash syntax:
|
19
20
|
#
|
@@ -23,7 +24,7 @@ module Libis
|
|
23
24
|
# p cfg.instance.my_value # => 10
|
24
25
|
# cfg.instance.my_text = 'abc'
|
25
26
|
# p cfg[:my_text] # => 'abc'
|
26
|
-
# p cfg.logger.warn('message') # => W, [2015-03-16T12:51:01.180548 #
|
27
|
+
# p cfg.logger.warn('message') # => W, [2015-03-16T12:51:01.180548 #123.456] WARN : message
|
27
28
|
#
|
28
29
|
class Config
|
29
30
|
include Singleton
|
@@ -33,6 +34,7 @@ module Libis
|
|
33
34
|
private
|
34
35
|
|
35
36
|
# For each configuration parameter, the value can be accessed via the class or the Singleton instance.
|
37
|
+
# The class diverts to the instance automatically.
|
36
38
|
def method_missing(name, *args, &block)
|
37
39
|
result = instance.send(name, *args, &block)
|
38
40
|
self === result ? self : result
|
@@ -40,6 +42,7 @@ module Libis
|
|
40
42
|
|
41
43
|
end
|
42
44
|
|
45
|
+
# Instance method that allows to access the configuration parameters by method.
|
43
46
|
def method_missing(name, *args, &block)
|
44
47
|
result = config.send(name, *args, &block)
|
45
48
|
self === config ? self : result
|
@@ -50,8 +53,10 @@ module Libis
|
|
50
53
|
# The file paths and Hashes are memorised and loaded again by the {#reload} methods.
|
51
54
|
# @param [String,Hash] file_or_hash
|
52
55
|
def <<(file_or_hash)
|
53
|
-
|
54
|
-
|
56
|
+
sync do
|
57
|
+
@config.send('<<', (file_or_hash)) { |data| @sources << data }
|
58
|
+
self
|
59
|
+
end
|
55
60
|
end
|
56
61
|
|
57
62
|
# Load all files and Hashes again.
|
@@ -59,10 +64,12 @@ module Libis
|
|
59
64
|
# Will not reset the configuration parameters. Parameters set directly on the
|
60
65
|
# configuration are kept intact unless they also exist in the files or hashes in which case they will be overwritten.
|
61
66
|
def reload
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
sync do
|
68
|
+
sources = @sources.dup
|
69
|
+
@sources.clear
|
70
|
+
sources.each { |f| self << f }
|
71
|
+
self
|
72
|
+
end
|
66
73
|
end
|
67
74
|
|
68
75
|
# Clear data and load all files and Hashes again.
|
@@ -71,8 +78,10 @@ module Libis
|
|
71
78
|
# added directly (not via file or hash) will no longer be available. Parameters set explicitly that also exist in
|
72
79
|
# the files or hashes will be reset to the values in those files and hashes.
|
73
80
|
def reload!
|
74
|
-
|
75
|
-
|
81
|
+
sync do
|
82
|
+
@config.clear!
|
83
|
+
reload
|
84
|
+
end
|
76
85
|
end
|
77
86
|
|
78
87
|
# Clear all data.
|
@@ -80,38 +89,57 @@ module Libis
|
|
80
89
|
# Not only all configuration parameters are deleted, but also the memorized list of loaded files
|
81
90
|
# and hashes are cleared and the logger configuration is reset to it's default status.
|
82
91
|
def clear!
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
92
|
+
sync do
|
93
|
+
@config.clear!
|
94
|
+
@sources = Array.new
|
95
|
+
self.logger
|
96
|
+
self
|
97
|
+
end
|
88
98
|
end
|
89
99
|
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
100
|
+
# Gets the default ::Logging formatter.
|
101
|
+
#
|
102
|
+
# This in an instance of a layout that prints in the default message format.
|
103
|
+
#
|
104
|
+
# The default layout prints log lines like this:
|
93
105
|
#
|
94
|
-
# <first char of severity>, [<timestamp
|
106
|
+
# <first char of severity>, [<timestamp> #<process-id>.<thread-id] <severity> : <message>
|
95
107
|
#
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
108
|
+
def get_log_formatter
|
109
|
+
# noinspection RubyResolve
|
110
|
+
::Logging::Layouts::Pattern.new(DEFAULT_LOG_LAYOUT_PARAMETERS)
|
111
|
+
end
|
112
|
+
|
113
|
+
def logger(name = nil)
|
114
|
+
sync do
|
115
|
+
name ||= :root
|
116
|
+
logger = ::Logging.logger[name]
|
117
|
+
logger.appenders = ::Logging.appenders.stdout(DEFAULT_LOG_LAYOUT_PARAMETERS) if logger.appenders.empty?
|
118
|
+
logger
|
102
119
|
end
|
103
120
|
end
|
104
121
|
|
105
|
-
attr_accessor :
|
122
|
+
attr_accessor :config, :sources
|
106
123
|
|
107
124
|
protected
|
108
125
|
|
109
126
|
def initialize(hash = nil, opts = {})
|
127
|
+
@mutex = ReentrantMutex.new
|
110
128
|
@config = ConfigFile.new(hash, opts)
|
111
129
|
self.clear!
|
112
130
|
end
|
113
131
|
|
132
|
+
def sync(&block)
|
133
|
+
@mutex.synchronize(&block)
|
134
|
+
end
|
135
|
+
|
136
|
+
::Logging::init
|
137
|
+
# noinspection RubyResolve
|
138
|
+
DEFAULT_LOG_LAYOUT_PARAMETERS = {
|
139
|
+
pattern: "%.1l, [%d #%p.%t] %#{::Logging::MAX_LEVEL_LENGTH}l : %m\n",
|
140
|
+
date_pattern: '%Y-%m-%dT%H:%M:%S.%L'
|
141
|
+
}
|
142
|
+
|
114
143
|
end
|
115
144
|
end
|
116
145
|
end
|
117
|
-
|