line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Config::Simple::Inherit; |
2
|
|
|
|
|
|
|
# package Simple::Inherit; |
3
|
|
|
|
|
|
|
|
4
|
2
|
|
|
2
|
|
124789
|
use warnings; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
83
|
|
5
|
2
|
|
|
2
|
|
12
|
use strict; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
81
|
|
6
|
2
|
|
|
2
|
|
12
|
use base qw( Config::Simple ); |
|
2
|
|
|
|
|
15
|
|
|
2
|
|
|
|
|
1169
|
|
7
|
2
|
|
|
2
|
|
24171
|
use UNIVERSAL qw( isa can ); |
|
2
|
|
|
|
|
30
|
|
|
2
|
|
|
|
|
11
|
|
8
|
|
|
|
|
|
|
# use UNIVERSAL qw( isa can VERSION ); |
9
|
2
|
|
|
2
|
|
2031
|
use Data::Dumper; |
|
2
|
|
|
|
|
11336
|
|
|
2
|
|
|
|
|
241
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.04'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
sub inherit { |
14
|
3
|
|
|
3
|
1
|
43474
|
my $class = shift; |
15
|
3
|
|
|
|
|
9
|
my $args = shift; |
16
|
|
|
|
|
|
|
# print STDERR Dumper(\$args); |
17
|
2
|
|
|
2
|
|
18
|
{ no strict 'refs'; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
722
|
|
|
3
|
|
|
|
|
8
|
|
18
|
3
|
100
|
66
|
|
|
38
|
unless(defined($args->{'base_config'}) && |
19
|
|
|
|
|
|
|
UNIVERSAL::isa($args->{'base_config'},'Config::Simple')) { |
20
|
|
|
|
|
|
|
# print STDERR "Now we create the first Config::Simple object using $args->{'filename'}; none already exists.\n"; |
21
|
|
|
|
|
|
|
# return "->inherit() has returned with debugging message."; |
22
|
1
|
|
|
|
|
7
|
return Config::Simple->new( filename => $args->{'filename'} ); |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
} |
25
|
2
|
|
|
|
|
4
|
my @cfg_filenames; |
26
|
2
|
|
|
|
|
7
|
my $cfg = $args->{'base_config'}; |
27
|
2
|
100
|
|
|
|
14
|
if(defined($cfg->{'_FILE_NAMES'})){ |
|
|
50
|
|
|
|
|
|
28
|
1
|
|
|
|
|
2
|
push @cfg_filenames, @{$cfg->{'_FILE_NAMES'}}; |
|
1
|
|
|
|
|
5
|
|
29
|
1
|
|
|
|
|
5
|
push @cfg_filenames, $args->{'filename'}; |
30
|
|
|
|
|
|
|
} elsif(defined($cfg->{'_FILE_NAME'})) { |
31
|
1
|
|
|
|
|
3
|
push @cfg_filenames, $cfg->{'_FILE_NAME'}; |
32
|
1
|
|
|
|
|
3
|
push @cfg_filenames, $args->{'filename'}; |
33
|
|
|
|
|
|
|
} else { |
34
|
0
|
|
|
|
|
0
|
die "We have a Config::Simple object, without an initial '_FILE_NAME' value.\n"; |
35
|
|
|
|
|
|
|
} |
36
|
2
|
|
|
|
|
5
|
$cfg->{'_FILE_NAMES'} = \@cfg_filenames; |
37
|
2
|
|
|
|
|
69
|
my $cfg_overload = Config::Simple->new( filename => $args->{'filename'} ); |
38
|
|
|
|
|
|
|
|
39
|
2
|
|
|
|
|
4248
|
foreach my $stanza_key (keys %{$cfg_overload->{'_DATA'}}){ |
|
2
|
|
|
|
|
14
|
|
40
|
2
|
|
|
|
|
4
|
foreach my $param_key (keys %{$cfg_overload->{'_DATA'}->{$stanza_key}}){ |
|
2
|
|
|
|
|
11
|
|
41
|
10
|
|
|
|
|
51
|
$cfg->{'_DATA'}->{$stanza_key}->{$param_key} = $cfg_overload->{'_DATA'}->{$stanza_key}->{$param_key}; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
2
|
|
|
|
|
18
|
return $cfg; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 NAME |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
Config::Simple::Inherit - Inherit values from, overwrite a base configuration |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head1 VERSION |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
Version 0.04 |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=cut |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head1 SYNOPSIS |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
my $installation_cfg = Config::Simple->new( |
61
|
|
|
|
|
|
|
file => '/etc/app_name/app_name.ini' ); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
my $client_cfg = Config::Simple::Inherit->inherit( |
64
|
|
|
|
|
|
|
base_config => $installation_cfg, |
65
|
|
|
|
|
|
|
filename => '/etc/app_name/client_name/app_name.ini', |
66
|
|
|
|
|
|
|
); |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
my $job_cfg = Config::Simple::Inherit->inherit( |
69
|
|
|
|
|
|
|
base_config => $client_cfg, |
70
|
|
|
|
|
|
|
filename => '/etc/app_name/client_name/app_job_id.ini', |
71
|
|
|
|
|
|
|
); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=head1 EXAMPLES |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
For details on accessing configuration parameters, read perldoc |
76
|
|
|
|
|
|
|
Config::Simple, which is well documented. In short, even if |
77
|
|
|
|
|
|
|
you wanted to bypass the published methods, everything seems |
78
|
|
|
|
|
|
|
to be found at: $cfg->{'_DATA'}->{$stanza}->{$key}, which then |
79
|
|
|
|
|
|
|
takes an anonymous list of whatever you feed it. The notes |
80
|
|
|
|
|
|
|
below focus on how to set up overloading configuration files |
81
|
|
|
|
|
|
|
How to write a constructor which will use them, how to share |
82
|
|
|
|
|
|
|
configuration hashes among modules in an application, etc. |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
These configuration hashes can be shared around with other |
85
|
|
|
|
|
|
|
objects which need them, like this: |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
my $object = My::New::Module->new({ 'cfg' => $self->{'cfg'} }); |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
assuming that you are inside an object method whose constructor |
90
|
|
|
|
|
|
|
stored the configuration hash at its own 'cfg' key, as I tend |
91
|
|
|
|
|
|
|
to do. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
or to needlessly duplicate the object in your memory overhead, |
94
|
|
|
|
|
|
|
as I did it when I was first digging around in the innards of |
95
|
|
|
|
|
|
|
Config::Simple, and learning how to use it: |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
my $new_object = My::New::Module->new({ |
98
|
|
|
|
|
|
|
'config_file' => $self->{'cfg'}->{'_FILE_NAME'} }); |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
Now I can write a constructor like this: |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=over |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
package My::New::Module; |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub new { |
107
|
|
|
|
|
|
|
my $class = shift; |
108
|
|
|
|
|
|
|
my $defaults = shift; |
109
|
|
|
|
|
|
|
my $self = {}; |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
if(defined($defaults->{'config_file'})){ |
112
|
|
|
|
|
|
|
$self->{'cfg'} = Config::Simple::Inherit->new( |
113
|
|
|
|
|
|
|
{ filename => $defaults->{'config_file'} } ); |
114
|
|
|
|
|
|
|
} elsif(defined($defaults->{'config_files'})){ |
115
|
|
|
|
|
|
|
my $cfg; |
116
|
|
|
|
|
|
|
undef($cfg); |
117
|
|
|
|
|
|
|
foreach my $file (@{$defaults->{'config_files'}}){ |
118
|
|
|
|
|
|
|
$cfg = Config::Simple::Inherit->inherit({ |
119
|
|
|
|
|
|
|
base_config => $cfg, |
120
|
|
|
|
|
|
|
filename => $file }); |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
$self->{'cfg'} = $cfg; |
123
|
|
|
|
|
|
|
} else { |
124
|
|
|
|
|
|
|
die "Constructor invoked with no Confirguration File." |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
my $db = $self->{'cfg'}->get_block('db'); |
128
|
|
|
|
|
|
|
# print STDERR Dumper(\$db); |
129
|
|
|
|
|
|
|
$self->{'dbh'} = My::New::Module::DB->connect($db); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
bless $self, $class; |
132
|
|
|
|
|
|
|
return $self; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=back |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
Making it possible to use it like so: |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
my $new_object = My::New::Module->new({ |
140
|
|
|
|
|
|
|
'config_files' => [ '/etc/my_app/base_configuration.ini', |
141
|
|
|
|
|
|
|
'/etc/my_app/client/client_configuration.ini', |
142
|
|
|
|
|
|
|
'/etc/my_app/client/job_id.ini' ] }); |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
with the job config over-writing the client config, over-writing |
145
|
|
|
|
|
|
|
the base config. If you let untrusted users write their |
146
|
|
|
|
|
|
|
own job configuration files, you probably want to reverse |
147
|
|
|
|
|
|
|
the order of the array, so that your base configuration file |
148
|
|
|
|
|
|
|
ultimately overwrites the final object with your sanity checks |
149
|
|
|
|
|
|
|
and security barriers in place. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=cut |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head1 METHODS |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
=head2 ->inherit() |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
This module only offers this one method, but I trust you'll |
158
|
|
|
|
|
|
|
find it useful. It returns a Config::Simple object, when given |
159
|
|
|
|
|
|
|
a reference to a hash, of which it only recognizes two keys: |
160
|
|
|
|
|
|
|
'base_config' and 'filename'. The 'base_config' ought to be |
161
|
|
|
|
|
|
|
left undefined or set to a 'Config::Simple' object created |
162
|
|
|
|
|
|
|
with either this method or the ->new() method provided by |
163
|
|
|
|
|
|
|
Config::Simple. When 'base_config' is given a Config::Simple |
164
|
|
|
|
|
|
|
object, it walks every configuration parameter defined in the |
165
|
|
|
|
|
|
|
filename, and uses the new value to update the value for the |
166
|
|
|
|
|
|
|
respective parameterin the 'base_config' object, inheriting |
167
|
|
|
|
|
|
|
values from it, but overloading the configuration with the |
168
|
|
|
|
|
|
|
new values. |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
I envision essentially two ways this module might be used: |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
(1) to provide a means for getting more specific with |
173
|
|
|
|
|
|
|
a configuration by first creating an installation-wide |
174
|
|
|
|
|
|
|
configuration, then a client specific configuration, then |
175
|
|
|
|
|
|
|
job specific configuration, each overloading the more general |
176
|
|
|
|
|
|
|
values provided by the configuration before it. |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
(2) to enforce client, and installation security controls and |
179
|
|
|
|
|
|
|
sanity checks on a configuration prepared by an untrusted user. |
180
|
|
|
|
|
|
|
Say you had an application which permitted a local user to |
181
|
|
|
|
|
|
|
create a configuration file for a job. By loading the user |
182
|
|
|
|
|
|
|
created configuration first, then using the installation |
183
|
|
|
|
|
|
|
default configuration to overwrite it, it would be possible |
184
|
|
|
|
|
|
|
to prevent abuse and enforce system wide constraints. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=cut |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
=head1 AUTHOR |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Hugh Esco, C<< >> |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head1 BUGS |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
195
|
|
|
|
|
|
|
C, or through the web interface at |
196
|
|
|
|
|
|
|
L. |
197
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
198
|
|
|
|
|
|
|
your bug as I make changes. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
I also do business as CampaignFoundations.com, |
201
|
|
|
|
|
|
|
where we host an issues que, available at: |
202
|
|
|
|
|
|
|
L |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head1 SUPPORT |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
perldoc Config::Simple::Inherit |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
You can also look for information at: |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
=over 4 |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
L |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=item * CPAN Ratings |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
L |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
L |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
I also watch for bug reports at: |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
L |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=item * Search CPAN |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
L |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=back |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
Sherzod B. Ruzmetov, author of Config::Simple, which I've come |
239
|
|
|
|
|
|
|
to rely on as the primary tool I use to manage configuration |
240
|
|
|
|
|
|
|
for the applications I write. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Copyright 2008 Hugh Esco, all rights reserved. |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
This program is released under the following license: Gnu |
247
|
|
|
|
|
|
|
Public License. |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=head1 SEE ALSO |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Config::Simple which handles ini, html and simple formats. |
252
|
|
|
|
|
|
|
Config::Simple::Inherit returns a Config::Simple object, and |
253
|
|
|
|
|
|
|
the accessors (and other methods) for its configuration are |
254
|
|
|
|
|
|
|
documented by Mr. Ruzmetov in the perldoc for his module. |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
If you need some combination of json, yaml, xml, perl, ini or |
257
|
|
|
|
|
|
|
Config::General formats, take a look at: Config::Merge, which I |
258
|
|
|
|
|
|
|
learned of after releasing version 0.03 of this module to cpan. |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=cut |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
1; # End of Config::Simple::Inherit |