3 CXGN::Config - L<Config::Any>-based implementation of cascading config files
7 my $cfg = MyProj::MyConfig->load_locked;
8 print "the basepath variable is $cfg->{basepath}\n";
12 Implementation of cascading config files.
18 =head2 1. Subclass CXGN::Config for your project's configuration
20 package MyProj::MyConfig;
21 use base 'CXGN::Config';
29 sub defaults { shift->SUPER::defaults( $defaults, @_ )}
36 my $cfg = MyProj::MyConfig->load_locked;
38 they will get a locked hashref of config values from the following
39 cascading sources, merged with later sources taking precedence:
43 =item defaults in CXGN::Config
45 =item defaults in any intermediate classes between CXGN::Config and MyProj::MyConfig
47 =item defaults in MyProj::MyConfig
49 =item values in /etc/cxgn/Global.conf
51 =item values in /etc/cxgn/MyProj.conf
55 load() also takes some optional arguments which can be used to tweak
56 which sources are used for configuration, etc.
73 our @search_path = $ENV{CXGN_CONF_DIR
}
74 ?
( $ENV{CXGN_CONF_DIR
} )
75 : map Cwd
::realpath
(File
::Spec
->rel2abs(File
::Spec
->catdir(@
$_))),
77 [ File
::Spec
->rootdir, 'etc', 'cxgn' ], # /etc/cxgn
85 Usage : my $cfg = MyProj::MyConfig->load();
86 Returns : hashref of merged config values
87 Args : optional hash-style list of options as:
89 name => conf file basename to load
90 default: first portion of class name, e.g.
91 'CXGN' for CXGN::Config
92 if 'undef' is passed, searches only Global.conf
94 add_vals => hashref of additional config values to
95 include, overriding any loaded ones
98 the following options are planned but not yet
101 add_files => arrayref of additional config files to
102 merge in, which will take precedence over
103 ones automatically discovered by this
108 Loads and merged multiple cascading config files. L<Config::Any> is
109 used for parsing each one.
111 Merge order (values in later files take precedence):
113 defaults in CXGN::Config
114 defaults in any intermediate classes between CXGN::Config and MyProj::MyConfig
115 defaults in MyProj::MyConfig
116 /etc/cxgn/Global.conf
117 /etc/cxgn/<name>.conf
119 B<NOTE:> For an additional layer of protection, consider using
120 L<"load_locked"> rather than C<load>.
125 my ( $class, %args ) = @_;
127 my @search_files = $class->_search_files( %args );
129 my @found_files = grep -f
, @search_files;
131 my $cfg = $class->defaults;
132 foreach my $file ( @found_files ) {
134 ->load_files({ files
=> [$file],
138 $c && @
$c or die "could not parse config file '$file'";
140 $class->_merge_hashes($cfg, $c->[0]->{$file});
143 if( my $v = $args{add_vals
} ) {
144 ref $v eq 'HASH' or croak
'add_vals must be a hashref';
145 $class->_merge_hashes($cfg, $v);
153 Same as load() above, but locks the hash with lock_hash() from
154 L<Hash::Util> before returning it.
156 This means that an error will be thrown if code tries to access a
157 configuration variable that is not set or change a configuration
158 variable, which provides a useful layer of error checking in many
161 Using this also provides a performance benefit, since the return value
162 of C<load_locked> is cached, while C<load> is not.
164 Most users of CXGN::Config-based modules will want to use
165 C<load_locked> rather than L<"load">.
169 Memoize
::memoize
'load_locked',
170 # normalize the args by adding the modification time of each file,
171 # so that the result will continue to be cached as long as the
172 # modification times of each of the files stays the same
175 my @search_files = $class->_search_files( @_ );
176 return join ',', ( $class, @_, map { $_ => (stat $_)[9] } @search_files );
182 my $cfg = $class->load(@_);
185 Hash
::Util
::lock_hashref
( $cfg );
190 # class method, takes the config name (like 'SGN'), and returns the
191 # list of full paths of files to search for
192 my %_search_files_cache;
194 my $result = $_search_files_cache{ join ',', @_ } ||= [ shift->__search_files(@_) ];
198 my ($class, %args) = @_;
201 my $cfg_name = exists $args{name
}
203 : $class->_conf_name;
205 my @conf_basenames = ('Global', defined $cfg_name ?
$cfg_name : () );
209 map File
::Spec
->catfile($path, "$_.conf" ), @conf_basenames;
213 # e.g. Foo::Conf::Baz->_conf_name returns 'Foo'
215 my $classname = shift;
216 return if $classname eq __PACKAGE__
; # don't search for CXGN.conf
217 my ($cn) = $classname =~ /^(?:CXGN::)?([^:]+)/
218 or die "error parsing class name $classname";
223 # merge all the other hashes into the first hash, modifying the first
230 $h1->{$_} = $h2->{$_};
239 Usage : CXGN::Config::MyConfig->merge_defaults({ foo => bar })
240 Returns : hashref of this class's default values merged with any
241 hashrefs that it is passed
242 Args : optional hashrefs of default values to merge in,
243 with the rightmost hash taking precedence
246 # recommended implementation in a CXGN::Config subclass:
253 # pass this class's defaults to the superclass, which will
254 # merge them into its own defaults and return the result
255 shift->SUPER::defaults( $defaults, @_ )
260 our $defaults; #< this hashref is filled below
262 #operate on a shallow copy of our defaults
263 return shift->_merge_hashes({%$defaults}, @_ );
268 #who to contact, these addresses will be used by modules which send us emails, among other things
269 email
=> 'sgn-feedback@solgenomics.net',
271 #default database to connect to and how to connect to it
272 dbhost
=> 'db.sgn.cornell.edu',
292 cview_db_backend
=> 'cxgn',
294 # path for cxgn core perllib
295 cxgn_core_perllib
=> '/data/local/cxgn/core/cxgn-corelibs/lib',
297 #how to find blast stuff
299 blast_db_path
=> '/data/shared/blast/databases/current',
301 #the shared temp directory used by cluster nodes
302 cluster_shared_tempdir
=> '/data/prod/tmp',
304 #how verbose we want the warnings to be in the apache error log
305 verbose_warnings
=> 1,
307 # Insitu file locations
308 insitu_fullsize_dir
=> '/data/prod/public/images/insitu/processed',
309 insitu_fullsize_url
=> '/data/images/insitu/processed',
310 insitu_display_dir
=> '/data/prod/public/images/insitu/display',
311 insitu_display_url
=> '/data/images/insitu/display',
312 insitu_input_dir
=> '/data/prod/public/images/insitu/incoming',
314 #path to our production ftp site
315 ftpsite_root
=> '/data/prod/public',
316 ftpsite_url
=> 'ftp://ftp.solgenomics.net',
318 #path to the pucebaboon temperature sensor file:
319 pucebaboon_file
=> '/data/prod/public/digitemp.out',
329 Robert Buels, E<lt>rmb32@cornell.eduE<gt>
331 =head1 COPYRIGHT & LICENSE
333 Copyright 2009 The Boyce Thompson Institute for Plant Research
335 This program is free software; you can redistribute it and/or modify
336 it under the same terms as Perl itself.