1 package OpenSRF::Utils::Config::Section;
5 use vars qw/@ISA $AUTOLOAD $VERSION/;
6 push @ISA, qw/OpenSRF::Utils/;
8 use OpenSRF::Utils (':common');
9 use Net::Domain qw/hostfqdn/;
11 $VERSION = do { my @r=(q$Revision$=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
16 #use overload '""' => \&OpenSRF::Utils::Config::dump_ini;
20 return $sec->__id(@_);
25 my $class = ref($self) || $self;
27 $self = bless {}, $class;
31 for my $line (@$lines) {
33 #($line) = split(/\s+\/\//, $line);
34 #($line) = split(/\s+#/, $line);
36 if ($line =~ /^\s*\[([^\[\]]+)\]/) {
37 $self->_sub_builder('__id');
42 my ($protokey,$value,$keytype,$key);
43 if ($line =~ /^([^=\s]+)\s*=\s*(.*)\s*$/s) {
44 ($protokey,$value) = ($1,$2);
45 ($keytype,$key) = split(/:/,$protokey);
48 $key = $protokey unless ($key);
50 if ($keytype ne $key) {
51 $keytype = lc $keytype;
52 if ($keytype eq 'list') {
53 $value = [split /\s*,\s*/, $value];
54 } elsif ($keytype eq 'bool') {
55 $value = do{ $value =~ /^t|y|1/i ? 1 : 0; };
56 } elsif ($keytype eq 'interval') {
57 $value = interval_to_seconds($value);
58 } elsif ($keytype eq 'subsection') {
59 if (exists $SECTIONCACHE{$value}) {
60 $value = $SECTIONCACHE{$value};
62 $SUBSECTION_FIXUP{$value}{$self->SECTION} = $key ;
68 $self->_sub_builder($key);
73 if (my $parent_def = $SUBSECTION_FIXUP{$self->SECTION}) {
74 my ($parent_section, $parent_key) = each %$parent_def;
75 $SECTIONCACHE{$parent_section}->{$parent_key} = $self;
76 delete $SUBSECTION_FIXUP{$self->SECTION};
79 $SECTIONCACHE{$self->SECTION} = $self;
84 package OpenSRF::Utils::Config;
86 use vars qw/@ISA $AUTOLOAD $VERSION $OpenSRF::Utils::ConfigCache/;
87 push @ISA, qw/OpenSRF::Utils/;
90 use OpenSRF::Utils (':common');
91 use OpenSRF::Utils::Logger;
92 use Net::Domain qw/hostfqdn/;
94 #use overload '""' => \&OpenSRF::Utils::Config::dump_ini;
98 my $config_file = shift;
100 return unless $config_file;
102 $class->load( config_file => $config_file);
110 if ($self->isa('OpenSRF::Utils::Config')) {
111 if (UNIVERSAL::isa(scalar(caller()), 'OpenSRF::Utils::Config' )) {
114 $string = "# Main File: " . $self->FILE . "\n\n" . $string;
117 for my $section ( ('__id', grep { $_ ne '__id' } sort keys %$self) ) {
118 next if ($section eq 'env' && $self->isa('OpenSRF::Utils::Config'));
119 if ($section eq '__id') {
120 $string .= '['.$self->SECTION."]\n" if ($self->isa('OpenSRF::Utils::Config::Section'));
121 } elsif (ref($self->$section)) {
122 if (ref($self->$section) =~ /ARRAY/o) {
123 $string .= "list:$section = ". join(', ', @{$self->$section}) . "\n";
124 } elsif (UNIVERSAL::isa($self->$section,'OpenSRF::Utils::Config::Section')) {
125 if ($self->isa('OpenSRF::Utils::Config::Section')) {
126 $string .= "subsection:$section = " . $self->$section->SECTION . "\n";
129 next if ($self->$section->{__sub} && !$included);
130 $string .= $self->$section . "\n";
132 } elsif (UNIVERSAL::isa($self->$section,'OpenSRF::Utils::Config')) {
133 $string .= $self->$section . "\n";
136 next if $section eq '__sub';
137 $string .= "$section = " . $self->$section . "\n";
141 $string =~ s/^/## /gm;
142 $string = "# Subfile: " . $self->FILE . "\n#" . '-'x79 . "\n".'#include "'.$self->FILE."\"\n". $string;
150 OpenSRF::Utils::Config
156 use OpenSRF::Utils::Config;
158 my $config_obj = OpenSRF::Utils::Config->load( config_file => '/config/file.cnf' );
160 my $attrs_href = $config_obj->attributes();
162 $config_obj->attributes->no_db(0);
164 open FH, '>'.$config_obj->FILE() . '.new';
165 print FH $config_obj;
173 This module is mainly used by other modules to load a configuration file.
179 Hashrefs of sections can be returned by calling a method of the object of the same name as the section.
180 They can be set by passing a hashref back to the same method. Sections will B<NOT> be autovivicated, though.
182 Here be a config file example, HAR!:
187 subsection:definition=devel_db
190 dsn=dbi:Pg(RaiseError => 0, AutoCommit => 1):dbname=dcl;host=nsite-dev
196 dsn=dbi:Pg(RaiseError => 0, AutoCommit => 1):dbname=dcl
202 subsection:definition=devel_rpc
214 url=https://localhost:9000/
219 SSL_key_file=client-key.pem
220 SSL_cert_file=client-cert.pem
221 SSL_ca_file=cacert.pem
225 base_dir=/home/miker/cvs/NOC/monitor_core/
235 $VERSION = do { my @r=(q$Revision$=~/\d+/g); sprintf "%d."."%02d"x$#r,@r };
238 =head2 OpenSRF::Utils::Config->load( config_file => '/some/config/file.cnf' )
240 Returns a OpenSRF::Utils::Config object representing the config file that was loaded.
241 The most recently loaded config file (hopefully the only one per app)
242 is stored at $OpenSRF::Utils::ConfigCache. Use OpenSRF::Utils::Config::current() to get at it.
249 $pkg = ref($pkg) || $pkg;
253 (my $new_pkg = $args{config_file}) =~ s/\W+/_/g;
254 $new_pkg .= "::$pkg";
255 $new_section_pkg .= "${new_pkg}::Section";
261 sub section_pkg { return '$new_section_pkg'; }
263 package $new_section_pkg;
264 use base "${pkg}::Section";
269 return $new_pkg->_load( %args );
274 $pkg = ref($pkg) || $pkg;
279 if ((exists $$self{config_file} and OpenSRF::Utils::Config->current) and (OpenSRF::Utils::Config->current->FILE eq $$self{config_file}) and (!$self->{force})) {
280 delete $$self{force};
281 return OpenSRF::Utils::Config->current();
284 $self->_sub_builder('__id');
285 $self->FILE($$self{config_file});
286 delete $$self{config_file};
287 return undef unless ($self->FILE);
289 $self->load_config();
291 $self->mangle_dirs();
292 $self->mangle_logs();
294 $OpenSRF::Utils::ConfigCache = $self unless $self->nocache;
295 delete $$self{nocache};
296 delete $$self{force};
304 my @parts = (grep { UNIVERSAL::isa($_,'OpenSRF::Utils::Config::Section') } values %$self);
306 my $must_match = scalar(keys %filters);
308 foreach my $part (@parts) {
310 for my $fkey (keys %filters) {
311 $part_count++ if ($part->$key eq $filters{$key});
313 push @ok_parts, $part if ($part_count == $must_match);
321 return $OpenSRF::Utils::ConfigCache;
325 return shift()->__id(@_);
330 my $host = hostfqdn();
332 $$self{env} = $self->section_pkg->new;
333 $$self{env}{hostname} = $host;
338 return unless ($self->logs && $self->dirs && $self->dirs->log_dir);
339 for my $i ( keys %{$self->logs} ) {
340 next if ($self->logs->$i =~ /^\//);
341 $self->logs->$i($self->dirs->log_dir."/".$self->logs->$i);
347 return unless ($self->dirs && $self->dirs->base_dir);
348 for my $i ( keys %{$self->dirs} ) {
349 if ( $i ne 'base_dir' ) {
350 next if ($self->dirs->$i =~ /^\//);
351 my $dir_tmp = $self->dirs->base_dir."/".$self->dirs->$i;
352 $dir_tmp =~ s#//#/#go;
353 $dir_tmp =~ s#/$##go;
354 $self->dirs->$i($dir_tmp);
361 my $config = new FileHandle $self->FILE, 'r';
363 OpenSRF::Utils::Logger->error("Could not open ".$self->FILE.": $!\n");
364 die "Could not open ".$self->FILE.": $!\n";
366 my @stripped_config = $self->__strip_comments($config) if (defined $config);
369 for my $line (@stripped_config) {
373 if ($line =~ /^\s*\[/ and @$chunk) {
374 my $section = $self->section_pkg->new($chunk);
376 my $sub_name = $section->SECTION;
377 $self->_sub_builder($sub_name);
378 $self->$sub_name($section);
380 #$self->{$section->SECTION} = $section;
386 if ($line =~ /^#\s*include\s+"(\S+)"\s*$/o) {
387 my $included_file = $1;
388 my $section = OpenSRF::Utils::Config->load(config_file => $included_file, nocache => 1);
390 my $sub_name = $section->FILE;
391 $self->_sub_builder($sub_name);
392 $self->$sub_name($section);
394 for my $subsect (keys %$section) {
395 next if ($subsect eq '__id');
397 $self->_sub_builder($subsect);
398 $self->$subsect($$section{$subsect});
400 #$self->$subsect($section->$subsect);
401 $self->$subsect->{__sub} = 1;
408 my $section = $self->section_pkg->new($chunk) if (@$chunk);
409 my $sub_name = $section->SECTION;
410 $self->_sub_builder($sub_name);
411 $self->$sub_name($section);
416 #------------------------------------------------------------------------------------------------------------------------------------
424 No know bugs, but report any to mrylander@gmail.com.
426 =head1 COPYRIGHT AND LICENSING
428 Mike Rylander, Copyright 2000-2007
430 The OpenSRF::Utils::Config module is free software. You may distribute under the terms
431 of the GNU General Public License version 2 or greater.