File Coverage

blib/lib/App/Open/Config.pm
Criterion Covered Total %
statement 119 134 88.8
branch 23 30 76.6
condition 9 10 90.0
subroutine 34 34 100.0
pod 8 8 100.0
total 193 216 89.3


line stmt bran cond sub pod time code
1             #===============================================================================
2             #
3             # FILE: Config.pm
4             #
5             # DESCRIPTION: App:;Open::Config - basic configuration interface to App::Open
6             #
7             # FILES: ---
8             # BUGS: ---
9             # NOTES: ---
10             # AUTHOR: Erik Hollensbe (),
11             # COMPANY:
12             # VERSION: 1.0
13             # CREATED: 06/02/2008 02:27:27 AM PDT
14             # REVISION: ---
15             #===============================================================================
16              
17             package App::Open::Config;
18              
19             =head2 METHODS
20              
21             =over 4
22              
23             =cut
24              
25 4     4   110272 use strict;
  4         11  
  4         912  
26 4     4   25 use warnings;
  4         10  
  4         124  
27              
28 4     4   10805 use YAML::Syck;
  4         22697  
  4         6875  
29             $YAML::Syck::ImplicitTyping = 1;
30              
31             =item new($config_file)
32              
33             Constructor, optionally takes the name of a config file; calls load_config()
34             automatically.
35              
36             =cut
37              
38             sub new {
39 24     24 1 4731 my ( $class, $config_file ) = @_;
40              
41 24   100     2043 my $self = bless { config_file => ( $config_file || "" ) }, $class;
42              
43 24         108 $self->load_config;
44              
45 22         147 return $self;
46             }
47              
48             =item load_config()
49              
50             Loads the configuration (or resets it). If there is trouble reading the
51             configuration, it will supply a default empty configuration.
52              
53             This call will die if the configuration is available, not undefined and does
54             not evaluate to a hash.
55              
56             =cut
57              
58             sub load_config {
59 24     24 1 277 my $self = shift;
60              
61 24         32 my $config;
62              
63 24         32 eval { $config = YAML::Syck::LoadFile( $self->{config_file} ) };
  24         213  
64              
65             # load a default configuration if Syck fails us
66 24 100 100     5797 $self->{config} = $@ ? {} : ( $config || {} );
67              
68 24 100 100     188 if ( !ref( $self->{config} ) || ref( $self->{config} ) ne 'HASH' ) {
69 2         27 die "INVALID_CONFIGURATION";
70             }
71              
72 22         44 return;
73             }
74              
75             =item load_backends(@backends)
76              
77             A frontend to load_backend(). Takes a list of backends to be processed in priority.
78              
79             =cut
80              
81             sub load_backends {
82 17     17 1 515 my ( $self, @backends ) = @_;
83              
84             #
85             # This is a lot more complex than I'd like, but it keeps the end-user
86             # configuration tolerable.
87             #
88             # Basically, if the backend value is a hash, it passes the key to
89             # load_backend() which will ferret the arguments out. The upside of this is
90             # that it's trivial to configure one backend, but multiple backends cannot
91             # guarantee ordering. The value associated with this key must be an array,
92             # and will be used as the arguments for the backend.
93             #
94             # If the value is an array, it expects each array element to be a hash,
95             # with the keys `name` and `args`, which represent the backend name and
96             # arguments respectively. The `args` must be an array. The whole top-level
97             # hash for the backend (the array element) is passed to load_backend().
98             #
99              
100 17 100 66     54 if ( exists( $self->config->{backend} )
101             and defined( $self->config->{backend} ) )
102             {
103 15 50       34 if (ref( $self->config->{backend} )) {
104 15 100       37 if (ref($self->config->{backend}) eq 'HASH') {
    50          
105 14         22 foreach my $backend ( keys %{ $self->config->{backend} } ) {
  14         37  
106 15         53 $self->load_backend($backend);
107             }
108             } elsif (ref($self->config->{backend}) eq 'ARRAY') {
109 1         2 foreach my $backend (@{$self->config->{backend}}) {
  1         2  
110 2 50       6 if (ref($backend) eq 'HASH') {
111 2         5 $self->load_backend($backend);
112             }
113             }
114             }
115             }
116             else {
117 0         0 $self->load_backend( $self->config->{backend} );
118             }
119             }
120              
121 17 100       60 if (@backends) {
122 5         11 foreach my $backend (@backends) {
123 6         15 $self->load_backend($backend);
124             }
125             }
126              
127 17         93 return;
128             }
129              
130             =item load_backend($backend)
131              
132             Gets the parameters for the backend, name and arguments. Requires the module
133             for the backend via require_backend() and on success, constructs an object from
134             that module with the supplied arguments and stores it in the backend list.
135              
136             The $backend argument can either be a hashref or string, this is detailed in
137             some comments in load_backends().
138              
139             If the backend supplied cannot be loaded, it will die with NO_BACKEND_FOUND.
140              
141             =cut
142              
143             sub load_backend {
144 25     25 1 99 my ( $self, $backend ) = @_;
145              
146 25 100       96 if (ref($backend) eq 'HASH') {
    50          
147 2 50       5 if ($backend->{name}) {
148 2         5 my $module = $self->require_backend($backend->{name});
149 2 50       5 if ($module) {
150 2         9 my $obj = $module->new($backend->{args});
151 2         12 push @{ $self->backend_order }, $obj;
  2         18  
152 2         16 return $module;
153             }
154             }
155             } elsif (!ref($backend)) {
156 23         66 my $module = $self->require_backend($backend);
157 23 50       58 if ($module) {
158 23         58 my $obj = $module->new( $self->config->{backend}{$backend} );
159 23         43 push @{ $self->backend_order }, $obj;
  23         63  
160 23         86 return $module;
161             }
162             }
163              
164 0         0 die "NO_BACKEND_FOUND $backend";
165             }
166              
167             =item require_backend($backend)
168              
169             Attempts to use the module that corresponds to the backend name. This will try
170             a couple of namespaces to load a backend:
171              
172             =over 4
173              
174             =item App::Open::Backend::
175              
176             =item "" (root namespace)
177              
178             =back
179              
180             On success, it will return the module name used. Otherwise, undef.
181              
182             =cut
183              
184             sub require_backend {
185 25     25 1 34 my ($self, $backend) = @_;
186              
187 25         50 foreach my $backend_try ( "App::Open::Backend::", "" ) {
188 34         112 my $module = "$backend_try$backend";
189              
190 34     3   2487 eval "use $module";
  3     3   1732  
  2     2   4  
  2     2   35  
  3     2   1577  
  3     2   8  
  3     2   69  
  2     2   14  
  2     2   3  
  2     1   31  
  2     1   649  
  1     1   1  
  1     1   19  
  2     1   13  
  2     1   3  
  2     1   32  
  2     1   16  
  2     1   4  
  2     1   35  
  2     1   487  
  1     1   2  
  1     1   18  
  2     1   13  
  2         4  
  2         31  
  2         13  
  2         5  
  2         29  
  1         467  
  0         0  
  0         0  
  1         6  
  1         3  
  1         18  
  1         7  
  1         1  
  1         16  
  1         437  
  0         0  
  0         0  
  1         5  
  1         2  
  1         12  
  1         512  
  0         0  
  0         0  
  1         6  
  1         3  
  1         17  
  1         6146  
  0         0  
  0         0  
  1         6  
  1         1  
  1         11  
  1         8  
  1         2  
  1         18  
  1         481  
  0         0  
  0         0  
  1         7  
  1         3  
  1         10  
  1         443  
  0         0  
  0         0  
  1         7  
  1         3  
  1         12  
191              
192 34 100       117 unless ($@) {
193 25         76 return $module;
194             }
195             }
196              
197 0         0 return undef;
198             }
199              
200             =item config()
201              
202             Convenience call to access the config hash.
203              
204             =cut
205              
206 101     101 1 548 sub config { $_[0]->{config} }
207              
208             =item config_file()
209              
210             Convenience call to access the config filename.
211              
212             =cut
213              
214 2     2 1 3588 sub config_file { $_[0]->{config_file} }
215              
216             =item backend_order()
217              
218             Returns the lookup order of the various MIME backends as arrayref.
219              
220             In the instance that this does not already exist when it is called, a new,
221             empty arrayref will be created and returned.
222              
223             =cut
224              
225             sub backend_order {
226 40     40 1 1112 my $self = shift;
227              
228 40 100       208 return $self->{backend_order} if ( $self->{backend_order} );
229              
230 17         63 return $self->{backend_order} = [];
231             }
232              
233             =back
234              
235             =cut
236              
237             1;