File Coverage

blib/lib/OpenPlugin/Config.pm
Criterion Covered Total %
statement 99 123 80.4
branch 26 52 50.0
condition 1 3 33.3
subroutine 16 20 80.0
pod 0 14 0.0
total 142 212 66.9


line stmt bran cond sub pod time code
1             package OpenPlugin::Config;
2              
3             # $Id: Config.pm,v 1.28 2003/04/28 17:43:48 andreychek Exp $
4              
5 6     6   7911 use strict;
  6         16  
  6         831  
6 6     6   41 use Cwd qw();
  6         12  
  6         131  
7 6     6   9828 use Data::Dumper qw( Dumper );
  6         66433  
  6         819  
8 6     6   77 use File::Basename qw();
  6         13  
  6         203  
9 6     6   37 use Log::Log4perl qw( get_logger );
  6         14  
  6         126  
10 6     6   458 use OpenPlugin::Plugin;
  6         15  
  6         17858  
11              
12             @OpenPlugin::Config::ISA = qw( OpenPlugin::Plugin );
13             $OpenPlugin::Config::VERSION = sprintf("%d.%02d", q$Revision: 1.28 $ =~ /(\d+)\.(\d+)/);
14              
15             # Package var to keep track of files read in. Is there a better way to do
16             # this?
17             #%OpenPlugin::ConfigFiles = {};
18              
19             my $logger = get_logger();
20              
21             ########################################
22             # CLASS METHODS
23             ########################################
24              
25             # This is the only place where we should have to specify information
26             # that is normally in the driver map. Otherwise we have a
27             # bootstrapping problem...
28              
29             my %CONFIG_CLASS = (
30             conf => 'OpenPlugin::Config::Conf',
31             ini => 'OpenPlugin::Config::Ini',
32             perl => 'OpenPlugin::Config::Perl',
33             xml => 'OpenPlugin::Config::XML',
34             );
35              
36              
37             sub get_config_driver {
38 13     13 0 137 my ( $class, $config_src, $config_type ) = @_;
39 13 50       53 unless ( $config_type ) {
40 13         193 ( $config_type ) = $config_src =~ /\.(\w+)\s*$/;
41             }
42 13         95 return $CONFIG_CLASS{ lc $config_type };
43             }
44              
45              
46             # Even if they're given a relative path, config implementations should
47             # use this to get the full configuration directory and filename so
48             # that 'Include' directives work as expected
49              
50             sub find_config_location {
51 12     12 0 28 my ( $class, $initial_filename, $other_root_dir ) = @_;
52 12         62 $logger->info( "Finding configuration location from ($initial_filename)" );
53              
54 12 100       198 return ( "", "" ) unless $initial_filename;
55              
56             # Get initial config dir, and untaint
57 7         574 my $initial_dir = File::Basename::dirname( $initial_filename );
58 7 50       4771 ( $initial_dir ) = $initial_dir =~ m/^(.*)$/ if -d $initial_dir;
59              
60             # Get the config file name, and untaint
61 7         265 my $config_file = File::Basename::basename( $initial_filename );
62 7 50       188 ( $config_file ) = $config_file =~ m/^(.*)$/ if -f $initial_filename;
63              
64             # Get the current working directory, and untaint
65 7         80429 my $current_dir = Cwd::cwd;
66 7 50       685 ( $current_dir ) = $current_dir =~ m/^(.*)$/ if -d $current_dir;
67              
68 7         214 chdir( $initial_dir );
69              
70             # Get path to the current dir, and untaint
71 7         118615 my $config_dir = Cwd::cwd;
72 7 50       1247 ( $config_dir ) = $config_dir =~ m/^(.*)$/ if -d $config_dir;
73              
74 7         137 chdir( $current_dir );
75 7 50       308 unless ( -f join( '/', $config_dir, $config_file ) ) {
76 0 0       0 if ( -f join( '/', $other_root_dir, $config_file ) ) {
77 0         0 $config_dir = $other_root_dir;
78             }
79             }
80 7         268 return ( $config_dir, $config_file );
81             }
82              
83             sub read {
84 12     12 0 49 my ( $self, $data ) = @_;
85              
86 12         21 my ( $full_filename, $config );
87 12 100       58 if( ref $data ne "HASH" ) {
88 7   33     244 $full_filename ||= join( '/', $self->{_m}{dir}, $self->{_m}{filename} );
89 7         196 $logger->info( "Trying to read file ($full_filename)" );
90              
91 7         574 my $config_class =
92             OpenPlugin::Config->get_config_driver( $full_filename,
93             $self->{_m}{type} );
94 7 50       58 unless ( $config_class ) {
95 0         0 die "Config is of unknown type! (Type: $self->{_m}{type} )";
96             }
97              
98             # The config drivers are defined at the top of this file, and are not
99             # tainted
100 7         1656 eval "require $config_class";
101 7         163 $config = $config_class->get_config( $full_filename );
102             }
103             else {
104 5         12 $config = $data;
105             }
106 12         30 foreach my $key ( keys %{ $config } ) {
  12         60  
107 19         79 $self->{$key} = $config->{$key};
108             }
109              
110             # Now see if there are any settings for 'Include'
111 12 100       90 if ( $self->{include} ) {
112 6         38 foreach my $src ( $self->get( 'include', 'src' ) ) {
113 6 50       32 next unless ( $src );
114 6         163 $logger->info( "Including file ($src)." );
115 6         63 $self->include( $src ) ;
116             }
117             }
118              
119 12         125 $logger->info( "Config file ($full_filename) read into object ok" );
120              
121 12         567 return $self;
122             }
123              
124              
125             ########################################
126             # PLUGIN INTERFACE
127             ########################################
128              
129 0     0 0 0 sub type { return 'config' }
130              
131 0     0 0 0 sub write {}
132              
133 6     6 0 98 sub meta_config_dir { return $_[0]->{_m}{dir} }
134 0     0 0 0 sub meta_config_file { return $_[0]->{_m}{filename} }
135 30     30 0 412 sub OP { return $_[0]->{_m}{OP} }
136              
137             sub init {
138 12     12 0 29 my ( $self, $params ) = @_;
139              
140 12         32 my $src = $params->{src};
141 12         23 my $dir = $params->{dir};
142              
143 12         52 my ( $config_dir, $filename ) = $self->find_config_location( $src, $dir );
144              
145             # Keep track of what has been read in
146 12         112 $self->{_m}{filename} = $filename;
147 12         65 $self->{_m}{dir} = $config_dir;
148 12         75 $self->{_m}{type} = $params->{type};
149 12         124 $self->{_m}{OP}{_toggle}{$filename} = 1;
150 12         492 return $self;
151             }
152              
153              
154             sub sections {
155 12     12 0 294 my ( $self ) = @_;
156 12         31 return grep ! /^_m$/, sort keys %{ $self };
  12         209  
157             }
158              
159             sub get {
160 222     222 0 1217 my ( $self, $section, @p ) = @_;
161 222 100       1345 my ( $sub_section, $param ) = ( $p[1] ) ? ( $p[0], $p[1] ) : ( undef, $p[0] );
162 222 100       1283 my $item = ( $sub_section )
163             ? $self->{ $section }{ $sub_section }{ $param }
164             : $self->{ $section }{ $param };
165 222 50       1289 return $item unless ( ref $item eq 'ARRAY' );
166 0 0       0 return wantarray ? @{ $item } : $item->[0];
  0         0  
167             }
168              
169             sub set {
170 216     216 0 407 my ( $self, $section, @p ) = @_;
171 216 50       1676 my ( $sub_section, $param, $value ) = ( $p[2] ) ? ( $p[0], $p[1], $p[2] ) : ( undef, $p[0], $p[1] );
172 216 50       1522 return $self->{ $section }{ $sub_section }{ $param } = $value if ( $sub_section );
173 0         0 return $self->{ $section }{ $param } = $value
174             }
175              
176              
177             sub delete {
178 0     0 0 0 my ( $self, $section, @p ) = @_;
179 0 0       0 my ( $sub_section, $param ) = ( $p[1] ) ? ( $p[0], $p[1] ) : ( undef, $p[0] );
180 0 0       0 if ( $sub_section ) {
    0          
181 0         0 $logger->info( "Deleting ($param) from sub-section ($section)($sub_section)" );
182 0         0 return delete $self->{ $section }{ $sub_section }{ $param };
183             }
184             elsif ( $param ) {
185 0         0 $logger->info( "Deleting ($param) from section ($section)" );
186 0         0 return delete $self->{ $section }{ $param };
187             }
188             else {
189 0         0 $logger->info( "Deleting section ($section)" );
190 0         0 return delete $self->{ $section };
191             }
192             }
193              
194              
195             # Allow a configuration to 'include' another configuration file -- it
196             # might be one of a different type too, so an INI file can include an
197             # XML file, etc.
198              
199             sub include {
200 6     6 0 14 my ( $self, $config_src ) = @_;
201              
202             # History tends to "repeat" itself if we don't learn it the first time ;-)
203 6 50       20 if ( $self->OP->{_toggle}{$config_src} ) {
204 0         0 $logger->warn("Attempt to include ($config_src), which is already loaded!");
205 0         0 return;
206             }
207              
208             # Flag this so we can tell we started processing this config
209 6         25 $self->OP->{_toggle}{$config_src} = 1;
210              
211             # Find out what type of configuration this is and read it in
212 6         99 my $config_class = $self->get_config_driver( $config_src );
213 6 50       102 unless ( $config_class ) {
214 0         0 die "Configuration ($config_src) cannot be included -- no valid ",
215             "configuration class found.\n";
216             }
217 6         40 $logger->info( "Trying to use class ($config_class) for included ",
218             "config ($config_src)" );
219 6         652 eval "require $config_class";
220              
221 6         55 my $include_config = OpenPlugin::Plugin->new( "config", $self, {
222             src => $config_src,
223             dir => $self->meta_config_dir })->read;
224              
225 6 50       95 if( $logger->is_debug ) {
226 0         0 $logger->debug( "Included config: ", Dumper( $include_config ) );
227             }
228              
229 6         137 $logger->info( "Sections of included config: ", join( ', ', $include_config->sections ) );
230 6         1147 foreach my $section ( $include_config->sections ) {
231 6         48 $logger->info( "Entering section ($section) of included config" );
232 6 50       319 next unless ( ref $include_config->{ $section } eq 'HASH' );
233 6         16 foreach my $param ( keys %{ $include_config->{ $section } } ) {
  6         44  
234              
235             # This section has a subsection, and $param is the subsection title
236              
237 72 50       561 if ( ref $include_config->{ $section }{ $param } eq 'HASH' ) {
238 72         1488 $logger->info( "($section)($param) is a hashref -- read in one at a time" );
239 72         498 foreach my $sub_param ( keys %{ $include_config->{ $section }{ $param } } ) {
  72         281  
240 216         871 $self->set( $section, $param, $sub_param,
241             $include_config->get( $section, $param, $sub_param ) );
242             }
243             }
244             else {
245 0         0 $logger->info( "($section)($param) is a value" );
246 0         0 $self->set( $section, $param, $include_config->get( $section, $param ) );
247             }
248             }
249             }
250 6         1022 return $include_config;
251             }
252              
253             1;
254              
255             __END__