| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # Manage dynamic configuration of modules. | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | package UR::ModuleConfig; | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | =pod | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | =head1 NAME | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | UR::ModuleConfig - manage dynamic configuration of modules. | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | package MyModule; | 
| 14 |  |  |  |  |  |  | use base qw(UR::ModuleConfig); | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | MyModule->config(%conf); | 
| 17 |  |  |  |  |  |  | $val = MyModule->config('key'); | 
| 18 |  |  |  |  |  |  | %conf = MyModule->config; | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | This module manages the configuration for modules.  Configurations can | 
| 23 |  |  |  |  |  |  | be read from files or set dynamically.  Modules wishing to use the | 
| 24 |  |  |  |  |  |  | configuration methods should inherit from the module. | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | =cut | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | # set up package | 
| 29 |  |  |  |  |  |  | require 5.006_000; | 
| 30 | 266 |  |  | 266 |  | 987 | use warnings; | 
|  | 266 |  |  |  |  | 336 |  | 
|  | 266 |  |  |  |  | 7487 |  | 
| 31 | 266 |  |  | 266 |  | 868 | use strict; | 
|  | 266 |  |  |  |  | 297 |  | 
|  | 266 |  |  |  |  | 9095 |  | 
| 32 |  |  |  |  |  |  | require UR; | 
| 33 |  |  |  |  |  |  | our $VERSION = "0.46"; # UR $VERSION;; | 
| 34 | 266 |  |  | 266 |  | 881 | use base qw(UR::ModuleBase); | 
|  | 266 |  |  |  |  | 320 |  | 
|  | 266 |  |  |  |  | 18861 |  | 
| 35 | 266 |  |  | 266 |  | 1020 | use IO::File; | 
|  | 266 |  |  |  |  | 313 |  | 
|  | 266 |  |  |  |  | 228449 |  | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | =pod | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | =head2 METHODS | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | The methods deal with managing configuration. | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | =cut | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | # hash containing all configuration information | 
| 46 |  |  |  |  |  |  | our %config; | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | # create a combined configuration hash from inheritance tree | 
| 49 |  |  |  |  |  |  | sub _inherit_config | 
| 50 |  |  |  |  |  |  | { | 
| 51 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 52 | 0 |  | 0 |  |  |  | my $class = ref($self) || $self; | 
| 53 |  |  |  |  |  |  |  | 
| 54 | 0 |  |  |  |  |  | my %cfg; | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | # get all packages inherited from | 
| 57 | 0 |  |  |  |  |  | my @inheritance = $self->inheritance; | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | # reverse loop through inheritance tree and construct config | 
| 60 | 0 |  |  |  |  |  | foreach my $cls (reverse(@inheritance)) | 
| 61 |  |  |  |  |  |  | { | 
| 62 | 0 | 0 |  |  |  |  | if (exists($config{$cls})) | 
| 63 |  |  |  |  |  |  | { | 
| 64 |  |  |  |  |  |  | # add hash, overriding previous values | 
| 65 | 0 |  |  |  |  |  | %cfg = (%cfg, %{$config{$cls}}); | 
|  | 0 |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | } | 
| 67 |  |  |  |  |  |  | } | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | # now add the current class config | 
| 70 | 0 | 0 |  |  |  |  | if (exists($config{$class})) | 
| 71 |  |  |  |  |  |  | { | 
| 72 | 0 |  |  |  |  |  | %cfg = (%cfg, %{$config{$class}}); | 
|  | 0 |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | } | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | # now add the object config | 
| 76 | 0 | 0 |  |  |  |  | if (ref($self)) | 
| 77 |  |  |  |  |  |  | { | 
| 78 |  |  |  |  |  |  | # add the objects config | 
| 79 | 0 | 0 |  |  |  |  | if (exists($config{"$class;$self"})) | 
| 80 |  |  |  |  |  |  | { | 
| 81 | 0 |  |  |  |  |  | %cfg = (%cfg, %{$config{"$class;$self"}}); | 
|  | 0 |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 0 |  |  |  |  |  | return %cfg; | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | =pod | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | =over 4 | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | =item config | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | MyModule->config(%config); | 
| 95 |  |  |  |  |  |  | $val = MyModule->config('key'); | 
| 96 |  |  |  |  |  |  | %conf = MyModule->config; | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | my $obj = MyModule->new; | 
| 99 |  |  |  |  |  |  | $obj->config(%config); | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | This method can be called three ways, as either a class or object | 
| 102 |  |  |  |  |  |  | method.  The first method takes a hash as its argument and sets the | 
| 103 |  |  |  |  |  |  | configuration parameters given in the hash.  The second method takes a | 
| 104 |  |  |  |  |  |  | single argument which should be one of the keys of the hash that set | 
| 105 |  |  |  |  |  |  | the config parameters and returns the value of that config hash key. | 
| 106 |  |  |  |  |  |  | The final method takes no arguments and returns the entire | 
| 107 |  |  |  |  |  |  | configuration hash. | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | When called as an object method, the config for both the object and | 
| 110 |  |  |  |  |  |  | all classes in its inheritance hierarchy are referenced, with the | 
| 111 |  |  |  |  |  |  | object config taking precedence over class methods and class methods | 
| 112 |  |  |  |  |  |  | closer to the object (first in the @ISA array) taking precedence over | 
| 113 |  |  |  |  |  |  | those further away (later in the @ISA array).  When called as a class | 
| 114 |  |  |  |  |  |  | method, the same procedure is used, except no object configuration is | 
| 115 |  |  |  |  |  |  | referenced. | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | Do not use configuration keys that begin with an underscore (C<_>). | 
| 118 |  |  |  |  |  |  | These are reserved for internal use. | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | =back | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | =cut | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | sub config | 
| 125 |  |  |  |  |  |  | { | 
| 126 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 127 | 0 |  | 0 |  |  |  | my $class = ref($self) || $self; | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | # handle both object and class configuration | 
| 130 | 0 |  |  |  |  |  | my $target; | 
| 131 | 0 | 0 |  |  |  |  | if (ref($self)) | 
| 132 |  |  |  |  |  |  | { | 
| 133 |  |  |  |  |  |  | # object config | 
| 134 | 0 |  |  |  |  |  | $target = "$class;$self"; | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  | else | 
| 137 |  |  |  |  |  |  | { | 
| 138 |  |  |  |  |  |  | # class config | 
| 139 | 0 |  |  |  |  |  | $target = $self; | 
| 140 |  |  |  |  |  |  | } | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | # lay claim to the modules configuration | 
| 143 | 0 |  |  |  |  |  | $config{$target}{_Manager} = __PACKAGE__; | 
| 144 |  |  |  |  |  |  |  | 
| 145 |  |  |  |  |  |  | # see if values are being set | 
| 146 | 0 | 0 |  |  |  |  | if (@_ > 1) | 
| 147 |  |  |  |  |  |  | { | 
| 148 |  |  |  |  |  |  | # set values in config hash, overriding any current values | 
| 149 | 0 |  |  |  |  |  | my (%opts) = @_; | 
| 150 | 0 |  |  |  |  |  | %{$config{$target}} = (%{$config{$target}}, %opts); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 151 | 0 |  |  |  |  |  | return 1; | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  | # else they want one key or the whole hash | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | # store config for object and inheritance tree | 
| 156 | 0 |  |  |  |  |  | my %cfg = $self->_inherit_config; | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | # see how we were called | 
| 159 | 0 | 0 |  |  |  |  | if (@_ == 1) | 
| 160 |  |  |  |  |  |  | { | 
| 161 |  |  |  |  |  |  | # return value of key | 
| 162 | 0 |  |  |  |  |  | my ($key) = @_; | 
| 163 |  |  |  |  |  |  | # make sure hash key exists | 
| 164 | 0 |  |  |  |  |  | my $val; | 
| 165 | 0 | 0 |  |  |  |  | if (exists($cfg{$key})) | 
| 166 |  |  |  |  |  |  | { | 
| 167 | 0 |  |  |  |  |  | $self->debug_message("config key $key exists"); | 
| 168 | 0 |  |  |  |  |  | $val = $cfg{$key}; | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  | else | 
| 171 |  |  |  |  |  |  | { | 
| 172 | 0 |  |  |  |  |  | $self->error_message("config key $key does not exist"); | 
| 173 | 0 |  |  |  |  |  | return; | 
| 174 |  |  |  |  |  |  | } | 
| 175 | 0 |  |  |  |  |  | return $val; | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  | # else return the entire config hash | 
| 178 | 0 |  |  |  |  |  | return %cfg; | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | =pod | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | =over 4 | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | =item check_config | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | $obj->check_config($key); | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | This method checks to see if a value is set.  Unlike config, it does | 
| 190 |  |  |  |  |  |  | not issue a warning if the key is not set.  If the key is not set, | 
| 191 |  |  |  |  |  |  | C is returned.  If the key has been set, the value of the key | 
| 192 |  |  |  |  |  |  | is returned (which may be C). | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  | =back | 
| 195 |  |  |  |  |  |  |  | 
| 196 |  |  |  |  |  |  | =cut | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | sub check_config | 
| 199 |  |  |  |  |  |  | { | 
| 200 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 201 |  |  |  |  |  |  |  | 
| 202 | 0 |  |  |  |  |  | my ($key) = @_; | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | # get config for inheritance tree | 
| 205 | 0 |  |  |  |  |  | my %cfg = $self->_inherit_config; | 
| 206 |  |  |  |  |  |  |  | 
| 207 | 0 | 0 |  |  |  |  | if (exists($cfg{$key})) | 
| 208 |  |  |  |  |  |  | { | 
| 209 | 0 |  |  |  |  |  | $self->debug_message("configuration key $key set: $cfg{$key}"); | 
| 210 | 0 |  |  |  |  |  | return $cfg{$key}; | 
| 211 |  |  |  |  |  |  | } | 
| 212 |  |  |  |  |  |  | # else | 
| 213 | 0 |  |  |  |  |  | $self->debug_message("configuration key $key not set"); | 
| 214 | 0 |  |  |  |  |  | return; | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | =pod | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | =over 4 | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | =item default_config | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | $class->default_config(%defaults); | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | This method allows the developer to set configuration values, only if | 
| 226 |  |  |  |  |  |  | they are not already set. | 
| 227 |  |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | =back | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | =cut | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  | sub default_config | 
| 233 |  |  |  |  |  |  | { | 
| 234 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 235 |  |  |  |  |  |  |  | 
| 236 | 0 |  |  |  |  |  | my (%opts) = @_; | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | # get config for inheritance tree | 
| 239 | 0 |  |  |  |  |  | my %cfg = $self->_inherit_config; | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | # loop through arguments | 
| 242 | 0 |  |  |  |  |  | while (my ($k, $v) = each(%opts)) | 
| 243 |  |  |  |  |  |  | { | 
| 244 |  |  |  |  |  |  | # see is config value is already set | 
| 245 | 0 | 0 |  |  |  |  | if (exists($cfg{$k})) | 
| 246 |  |  |  |  |  |  | { | 
| 247 | 0 |  |  |  |  |  | $self->debug_message("config $k already set"); | 
| 248 | 0 |  |  |  |  |  | next; | 
| 249 |  |  |  |  |  |  | } | 
| 250 | 0 |  |  |  |  |  | $self->debug_message("setting default for $k"); | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | # set config key | 
| 253 | 0 |  |  |  |  |  | $self->config($k => $v); | 
| 254 |  |  |  |  |  |  | } | 
| 255 |  |  |  |  |  |  |  | 
| 256 | 0 |  |  |  |  |  | return 1; | 
| 257 |  |  |  |  |  |  | } | 
| 258 |  |  |  |  |  |  |  | 
| 259 |  |  |  |  |  |  | =pod | 
| 260 |  |  |  |  |  |  |  | 
| 261 |  |  |  |  |  |  | =over 4 | 
| 262 |  |  |  |  |  |  |  | 
| 263 |  |  |  |  |  |  | =item config_file | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | $rv = $class->config_file(path => $path); | 
| 266 |  |  |  |  |  |  | $rv = $class->config_file(handle => $fh); | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | This method reads in the given file and expects key-value pairs, one | 
| 269 |  |  |  |  |  |  | per line.  The key and value should be separated by an equal sign, | 
| 270 |  |  |  |  |  |  | C<=>, with optional surrounding space.  It currently only handles | 
| 271 |  |  |  |  |  |  | single value values. | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | The method returns true upon success, C on failure. | 
| 274 |  |  |  |  |  |  |  | 
| 275 |  |  |  |  |  |  | =back | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | =cut | 
| 278 |  |  |  |  |  |  |  | 
| 279 |  |  |  |  |  |  | sub config_file | 
| 280 |  |  |  |  |  |  | { | 
| 281 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 282 |  |  |  |  |  |  |  | 
| 283 | 0 |  |  |  |  |  | my (%opts) = @_; | 
| 284 |  |  |  |  |  |  |  | 
| 285 | 0 |  |  |  |  |  | my $fh; | 
| 286 | 0 | 0 |  |  |  |  | if ($opts{path}) | 
|  |  | 0 |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | { | 
| 288 |  |  |  |  |  |  | # make sure file is ok | 
| 289 | 0 | 0 |  |  |  |  | if (-f $opts{path}) | 
| 290 |  |  |  |  |  |  | { | 
| 291 | 0 |  |  |  |  |  | $self->debug_message("config file exists: $opts{path}"); | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  | else | 
| 294 |  |  |  |  |  |  | { | 
| 295 | 0 |  |  |  |  |  | $self->error_message("config file does not exist: $opts{path}"); | 
| 296 | 0 |  |  |  |  |  | return; | 
| 297 |  |  |  |  |  |  | } | 
| 298 | 0 | 0 |  |  |  |  | if (-r $opts{path}) | 
| 299 |  |  |  |  |  |  | { | 
| 300 | 0 |  |  |  |  |  | $self->debug_message("config file is readable: $opts{path}"); | 
| 301 |  |  |  |  |  |  | } | 
| 302 |  |  |  |  |  |  | else | 
| 303 |  |  |  |  |  |  | { | 
| 304 | 0 |  |  |  |  |  | $self->error_message("config file is not readable: $opts{path}"); | 
| 305 | 0 |  |  |  |  |  | return; | 
| 306 |  |  |  |  |  |  | } | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | # open file | 
| 309 | 0 |  |  |  |  |  | $fh = IO::File->new("<$opts{path}"); | 
| 310 | 0 | 0 |  |  |  |  | if (defined($fh)) | 
| 311 |  |  |  |  |  |  | { | 
| 312 | 0 |  |  |  |  |  | $self->debug_message("opened config file for reading: $opts{path}"); | 
| 313 |  |  |  |  |  |  | } | 
| 314 |  |  |  |  |  |  | else | 
| 315 |  |  |  |  |  |  | { | 
| 316 |  |  |  |  |  |  | $self->error_message("failed to open config file for reading: " | 
| 317 | 0 |  |  |  |  |  | . $opts{path}); | 
| 318 | 0 |  |  |  |  |  | return; | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  | } | 
| 321 |  |  |  |  |  |  | elsif ($opts{handle}) | 
| 322 |  |  |  |  |  |  | { | 
| 323 | 0 |  |  |  |  |  | $fh = $opts{handle}; | 
| 324 |  |  |  |  |  |  | } | 
| 325 |  |  |  |  |  |  | else | 
| 326 |  |  |  |  |  |  | { | 
| 327 | 0 |  |  |  |  |  | $self->error_message("no config file input specified"); | 
| 328 | 0 |  |  |  |  |  | return; | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | # read through file | 
| 332 | 0 |  |  |  |  |  | my %fconfig; | 
| 333 | 0 |  |  |  |  |  | while (defined(my $line = $fh->getline)) | 
| 334 |  |  |  |  |  |  | { | 
| 335 |  |  |  |  |  |  | # clean up | 
| 336 | 0 |  |  |  |  |  | chomp($line); | 
| 337 | 0 |  |  |  |  |  | $line =~ s/\#.*//; | 
| 338 | 0 |  |  |  |  |  | $line =~ s/^\s*//; | 
| 339 | 0 |  |  |  |  |  | $line =~ s/\s*$//; | 
| 340 | 0 | 0 |  |  |  |  | next unless $line =~ m/\S/; | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  | # parse | 
| 343 | 0 |  |  |  |  |  | my ($k, $v) = split(m/\s*=\s*/, $line, 2); | 
| 344 | 0 |  |  |  |  |  | $fconfig{$k} = $v; | 
| 345 |  |  |  |  |  |  | } | 
| 346 | 0 |  |  |  |  |  | $fh->close; | 
| 347 |  |  |  |  |  |  |  | 
| 348 |  |  |  |  |  |  | # update config | 
| 349 | 0 |  |  |  |  |  | return $self->config(%fconfig); | 
| 350 |  |  |  |  |  |  | } | 
| 351 |  |  |  |  |  |  |  | 
| 352 |  |  |  |  |  |  | 1; | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | #$Header$ |