| 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 |