File Coverage

blib/lib/Log/Log4perl/Config.pm
Criterion Covered Total %
statement 336 372 90.3
branch 157 194 80.9
condition 28 39 71.7
subroutine 35 36 97.2
pod 0 24 0.0
total 556 665 83.6


line stmt bran cond sub pod time code
1             ##################################################
2             ##################################################
3             use 5.006;
4 70     70   1254 use strict;
  70         251  
5 70     70   446 use warnings;
  70         147  
  70         1586  
6 70     70   367  
  70         155  
  70         2074  
7             use Log::Log4perl::Logger;
8 70     70   416 use Log::Log4perl::Level;
  70         157  
  70         2316  
9 70     70   477 use Log::Log4perl::Config::PropertyConfigurator;
  70         173  
  70         540  
10 70     70   31880 use Log::Log4perl::JavaMap;
  70         191  
  70         2094  
11 70     70   30295 use Log::Log4perl::Filter;
  70         205  
  70         2479  
12 70     70   545 use Log::Log4perl::Filter::Boolean;
  70         172  
  70         1724  
13 70     70   30831 use Log::Log4perl::Config::Watch;
  70         210  
  70         1945  
14 70     70   31945  
  70         216  
  70         2583  
15             use constant _INTERNAL_DEBUG => 0;
16 70     70   503  
  70         170  
  70         360040  
17             our $CONFIG_FILE_READS = 0;
18             our $CONFIG_INTEGRITY_CHECK = 1;
19             our $CONFIG_INTEGRITY_ERROR = undef;
20              
21             our $WATCHER;
22             our $DEFAULT_WATCH_DELAY = 60; # seconds
23             our $OPTS = {};
24             our $OLD_CONFIG;
25             our $LOGGERS_DEFINED;
26             our $UTF8 = 0;
27              
28             ###########################################
29             ###########################################
30             Log::Log4perl::Logger->reset();
31              
32 178     178 0 945 undef $WATCHER; # just in case there's a one left over (e.g. test cases)
33              
34 178         320 return _init(@_);
35             }
36 178         544  
37             ###########################################
38             ###########################################
39             my( $class, $flag ) = @_;
40              
41             $UTF8 = $flag if defined $flag;
42 1     1 0 682  
43             return $UTF8;
44 1 50       5 }
45              
46 1         2 ###########################################
47             ###########################################
48             return $WATCHER;
49             }
50              
51             ###########################################
52 2     2 0 13 ###########################################
53             my ($class, $config, $delay, $opts) = @_;
54             # delay can be a signal name - in this case we're gonna
55             # set up a signal handler.
56              
57             if(defined $WATCHER) {
58 9     9 0 39 $config = $WATCHER->file();
59             if(defined $Log::Log4perl::Config::Watch::SIGNAL_CAUGHT) {
60             $delay = $WATCHER->signal();
61             } else {
62 9 100       32 $delay = $WATCHER->check_interval();
63 6         29 }
64 6 100       23 }
65 1         2  
66             print "init_and_watch ($config-$delay). Resetting.\n" if _INTERNAL_DEBUG;
67 5         21  
68             Log::Log4perl::Logger->reset();
69              
70             defined ($delay) or $delay = $DEFAULT_WATCH_DELAY;
71 9         19  
72             if (ref $config) {
73 9         57 die "Log4perl can only watch a file, not a string of " .
74             "configuration information";
75 9 50       31 }elsif ($config =~ m!^(https?|ftp|wais|gopher|file):!){
76             die "Log4perl can only watch a file, not a url like $config";
77 9 50       67 }
    50          
78 0         0  
79             if($delay =~ /\D/) {
80             $WATCHER = Log::Log4perl::Config::Watch->new(
81 0         0 file => $config,
82             signal => $delay,
83             l4p_internal => 1,
84 9 100       57 );
85 2         14 } else {
86             $WATCHER = Log::Log4perl::Config::Watch->new(
87             file => $config,
88             check_interval => $delay,
89             l4p_internal => 1,
90             );
91 7         65 }
92              
93             if(defined $opts) {
94             die "Parameter $opts needs to be a hash ref" if ref($opts) ne "HASH";
95             $OPTS = $opts;
96             }
97              
98 9 100       37 eval { _init($class, $config); };
99 1 50       6  
100 1         4 if($@) {
101             die "$@" unless defined $OLD_CONFIG;
102             # Call _init with a pre-parsed config to go back to old setting
103 9         23 _init($class, undef, $OLD_CONFIG);
  9         38  
104             warn "Loading new config failed, reverted to old one\n";
105 9 50       42 }
106 0 0       0 }
107              
108 0         0 ##################################################
109 0         0 ##################################################
110             my($class, $config, $data) = @_;
111              
112             my %additivity = ();
113              
114             $LOGGERS_DEFINED = 0;
115              
116 187     187   513 print "Calling _init\n" if _INTERNAL_DEBUG;
117              
118 187         375 #keep track so we don't create the same one twice
119             my %appenders_created = ();
120 187         362  
121             #some appenders need to run certain subroutines right at the
122 187         284 #end of the configuration phase, when all settings are in place.
123             my @post_config_subs = ();
124              
125 187         351 # This logic is probably suited to win an obfuscated programming
126             # contest. It desperately needs to be rewritten.
127             # Basically, it works like this:
128             # config_read() reads the entire config file into a hash of hashes:
129 187         348 # log4j.logger.foo.bar.baz: WARN, A1
130             # gets transformed into
131             # $data->{log4j}->{logger}->{foo}->{bar}->{baz} = "WARN, A1";
132             # The code below creates the necessary loggers, sets the appenders
133             # and the layouts etc.
134             # In order to transform parts of this tree back into identifiers
135             # (like "foo.bar.baz"), we're using the leaf_paths functions below.
136             # Pretty scary. But it allows the lines of the config file to be
137             # in *arbitrary* order.
138              
139             $data = config_read($config) unless defined $data;
140            
141             if(_INTERNAL_DEBUG) {
142             require Data::Dumper;
143             Data::Dumper->import();
144             print Data::Dumper::Dumper($data);
145 187 50       752 }
146              
147 178         354 my @loggers = ();
148             my %filter_names = ();
149              
150             my $system_wide_threshold;
151              
152             # Autocorrect the rootlogger/rootLogger typo
153 178         396 if(exists $data->{rootlogger} and
154 178         363 ! exists $data->{rootLogger}) {
155             $data->{rootLogger} = $data->{rootlogger};
156 178         292 }
157              
158             # Find all logger definitions in the conf file. Start
159 178 100 66     653 # with root loggers.
160             if(exists $data->{rootLogger}) {
161 1         5 $LOGGERS_DEFINED++;
162             push @loggers, ["", $data->{rootLogger}->{value}];
163             }
164            
165             # Check if we've got a system-wide threshold setting
166 178 100       528 if(exists $data->{threshold}) {
167 27         61 # yes, we do.
168 27         89 $system_wide_threshold = $data->{threshold}->{value};
169             }
170              
171             if (exists $data->{oneMessagePerAppender}){
172 178 100       523 $Log::Log4perl::one_message_per_appender =
173             $data->{oneMessagePerAppender}->{value};
174 4         6 }
175              
176             if(exists $data->{utcDateTimes}) {
177 178 100       471 require Log::Log4perl::DateFormat;
178             # Need to split this up in two lines, or CVS will
179 1         3 # mess it up.
180             $Log::Log4perl::DateFormat::GMTIME =
181             !!$data->{utcDateTimes}->{value};
182 178 100       480 }
183 2         13  
184             # Boolean filters
185             my %boolean_filters = ();
186              
187 2         15 # Continue with lower level loggers. Both 'logger' and 'category'
188             # are valid keywords. Also 'additivity' is one, having a logger
189             # attached. We'll differentiate between the two further down.
190             for my $key (qw(logger category additivity PatternLayout filter)) {
191 178         343  
192             if(exists $data->{$key}) {
193              
194             for my $path (@{leaf_paths($data->{$key})}) {
195              
196 178         427 print "Path before: @$path\n" if _INTERNAL_DEBUG;
197              
198 889 100       1932 my $value = boolean_to_perlish(pop @$path);
199              
200 162         274 pop @$path; # Drop the 'value' keyword part
  162         482  
201              
202 223         341 if($key eq "additivity") {
203             # This isn't a logger but an additivity setting.
204 223         625 # Save it in a hash under the logger's name for later.
205             $additivity{join('.', @$path)} = $value;
206 223         559  
207             #a global user-defined conversion specifier (cspec)
208 223 100       792 }elsif ($key eq "PatternLayout"){
    100          
    100          
209             &add_global_cspec(@$path[-1], $value);
210              
211 3         22 }elsif ($key eq "filter"){
212             print "Found entry @$path\n" if _INTERNAL_DEBUG;
213             $filter_names{@$path[0]}++;
214             } else {
215 3         21  
216             if (ref($value) eq "ARRAY") {
217             die "Multiple definitions of logger ".join('.',@$path)." in log4perl config";
218 52         58 }
219 52         117  
220             # This is a regular logger
221             $LOGGERS_DEFINED++;
222 165 50       463 push @loggers, [join('.', @$path), $value];
223 0         0 }
224             }
225             }
226             }
227 165         292  
228 165         732 # Now go over all filters found by name
229             for my $filter_name (sort keys %filter_names) {
230              
231             print "Checking filter $filter_name\n" if _INTERNAL_DEBUG;
232              
233             # The boolean filter needs all other filters already
234             # initialized, defer its initialization
235 177         612 if($data->{filter}->{$filter_name}->{value} eq
236             "Log::Log4perl::Filter::Boolean") {
237 22         27 print "Boolean filter ($filter_name)\n" if _INTERNAL_DEBUG;
238             $boolean_filters{$filter_name}++;
239             next;
240             }
241 22 100       61  
242             my $type = $data->{filter}->{$filter_name}->{value};
243 3         7 if(my $code = compile_if_perl($type)) {
244 3         6 $type = $code;
245 3         7 }
246            
247             print "Filter $filter_name is of type $type\n" if _INTERNAL_DEBUG;
248 19         35  
249 19 100       32 my $filter;
250 4         9  
251             if(ref($type) eq "CODE") {
252             # Subroutine - map into generic Log::Log4perl::Filter class
253 18         29 $filter = Log::Log4perl::Filter->new($filter_name, $type);
254             } else {
255 18         23 # Filter class
256             die "Filter class '$type' doesn't exist" unless
257 18 100       42 Log::Log4perl::Util::module_available($type);
258             eval "require $type" or die "Require of $type failed ($!)";
259 4         23  
260             # Invoke with all defined parameter
261             # key/values (except the key 'value' which is the entry
262 14 100       47 # for the class)
263             $filter = $type->new(name => $filter_name,
264 13 50       837 map { $_ => $data->{filter}->{$filter_name}->{$_}->{value} }
265             grep { $_ ne "value" }
266             sort keys %{$data->{filter}->{$filter_name}});
267             }
268             # Register filter with the global filter registry
269             $filter->register();
270 27         110 }
271 40         86  
272 13         56 # Initialize boolean filters (they need the other filters to be
  13         74  
273             # initialized to be able to compile their logic)
274             for my $name (sort keys %boolean_filters) {
275 16         88 my $logic = $data->{filter}->{$name}->{logic}->{value};
276             die "No logic defined for boolean filter $name" unless defined $logic;
277             my $filter = Log::Log4perl::Filter::Boolean->new(
278             name => $name,
279             logic => $logic);
280 174         848 $filter->register();
281 3         8 }
282 3 50       11  
283 3         23 for (@loggers) {
284             my($name, $value) = @$_;
285              
286 3         19 my $logger = Log::Log4perl::Logger->get_logger($name);
287             my ($level, @appnames) = split /\s*,\s*/, $value;
288              
289 174         440 $logger->level(
290 188         476 Log::Log4perl::Level::to_priority($level),
291             'dont_reset_all');
292 188         884  
293 188         1410 if(exists $additivity{$name}) {
294             $logger->additivity($additivity{$name}, 1);
295 188         761 }
296              
297             for my $appname (@appnames) {
298              
299 187 100       563 my $appender = create_appender_instance(
300 3         14 $data, $appname, \%appenders_created, \@post_config_subs,
301             $system_wide_threshold);
302              
303 187         400 $logger->add_appender($appender, 'dont_reset_all');
304             set_appender_by_name($appname, $appender, \%appenders_created);
305 193         797 }
306             }
307              
308             #run post_config subs
309 183         842 for(@post_config_subs) {
310 183         574 $_->();
311             }
312              
313             #now we're done, set up all the output methods (e.g. ->debug('...'))
314             Log::Log4perl::Logger::reset_all_output_methods();
315 163         565  
316 11         31 #Run a sanity test on the config not disabled
317             if($Log::Log4perl::Config::CONFIG_INTEGRITY_CHECK and
318             !config_is_sane()) {
319             warn "Log::Log4perl configuration looks suspicious: ",
320 163         569 "$CONFIG_INTEGRITY_ERROR";
321             }
322              
323 163 100 100     869 # Successful init(), save config for later
324             $OLD_CONFIG = $data;
325 5         136  
326             $Log::Log4perl::Logger::INITIALIZED = 1;
327             }
328              
329             ##################################################
330 163         861 ##################################################
331             if(! $LOGGERS_DEFINED) {
332 163         885 $CONFIG_INTEGRITY_ERROR = "No loggers defined";
333             return 0;
334             }
335              
336             if(scalar keys %Log::Log4perl::Logger::APPENDER_BY_NAME == 0) {
337             $CONFIG_INTEGRITY_ERROR = "No appenders defined";
338 154 100   154 0 449 return 0;
339 4         9 }
340 4         13  
341             return 1;
342             }
343 150 100       573  
344 1         3 ##################################################
345 1         4 ##################################################
346             my($data, $appname, $appenders_created, $post_config_subs,
347             $system_wide_threshold) = @_;
348 149         595  
349             my $appenderclass = get_appender_by_name(
350             $data, $appname, $appenders_created);
351              
352             print "appenderclass=$appenderclass\n" if _INTERNAL_DEBUG;
353              
354 204     204 0 714 my $appender;
355              
356             if (ref $appenderclass) {
357 204         612 $appender = $appenderclass;
358             } else {
359             die "ERROR: you didn't tell me how to " .
360 204         350 "implement your appender '$appname'"
361             unless $appenderclass;
362 204         336  
363             if (Log::Log4perl::JavaMap::translate($appenderclass)){
364 204 100       592 # It's Java. Try to map
365 10         26 print "Trying to map Java $appname\n" if _INTERNAL_DEBUG;
366             $appender = Log::Log4perl::JavaMap::get($appname,
367 194 100       867 $data->{appender}->{$appname});
368              
369             }else{
370             # It's Perl
371 193 100       790 my @params = grep { $_ ne "layout" and
372             $_ ne "value"
373 13         27 } sort keys %{$data->{appender}->{$appname}};
374            
375 13         152 my %param = ();
376             foreach my $pname (@params){
377             #this could be simple value like
378             #{appender}{myAppender}{file}{value} => 'log.txt'
379 544 100       2128 #or a structure like
380             #{appender}{myAppender}{login} =>
381 180         377 # { name => {value => 'bob'},
  180         879  
382             # pwd => {value => 'xxx'},
383 180         424 # }
384 180         403 #in the latter case we send a hashref to the appender
385             if (exists $data->{appender}{$appname}
386             {$pname}{value} ) {
387             $param{$pname} = $data->{appender}{$appname}
388             {$pname}{value};
389             }else{
390             $param{$pname} = {map {$_ => $data->{appender}
391             {$appname}
392             {$pname}
393 197 100       464 {$_}
394             {value}}
395             sort keys %{$data->{appender}
396 192         490 {$appname}
397             {$pname}}
398             };
399             }
400            
401             }
402 14         51  
403 5         17 my $depends_on = [];
404            
405 5         24 $appender = Log::Log4perl::Appender->new(
406             $appenderclass,
407             name => $appname,
408             l4p_post_config_subs => $post_config_subs,
409             l4p_depends_on => $depends_on,
410             %param,
411 180         451 );
412            
413 180         1152 for my $dependency (@$depends_on) {
414             # If this appender indicates that it needs other appenders
415             # to exist (e.g. because it's a composite appender that
416             # relays messages on to its appender-refs) then we're
417             # creating their instances here. Reason for this is that
418             # these appenders are not attached to any logger and are
419             # therefore missed by the config parser which goes through
420             # the defined loggers and just creates *their* attached
421 178         628 # appenders.
422             $appender->composite(1);
423             next if exists $appenders_created->{$appname};
424             my $app = create_appender_instance($data, $dependency,
425             $appenders_created,
426             $post_config_subs);
427             # If the appender appended a subroutine to $post_config_subs
428             # (a reference to an array of subroutines)
429             # here, the configuration parser will later execute this
430 11         36 # method. This is used by a composite appender which needs
431 11 50       31 # to make sure all of its appender-refs are available when
432 11         39 # all configuration settings are done.
433              
434             # Smuggle this sub-appender into the hash of known appenders
435             # without attaching it to any logger directly.
436             $
437             Log::Log4perl::Logger::APPENDER_BY_NAME{$dependency} = $app;
438             }
439             }
440             }
441              
442             add_layout_by_name($data, $appender, $appname) unless
443             $appender->composite();
444              
445 11         48 # Check for appender thresholds
446             my $threshold =
447             $data->{appender}->{$appname}->{Threshold}->{value};
448              
449             if(defined $system_wide_threshold and
450 201 100       633 !defined $threshold) {
451             $threshold = $system_wide_threshold;
452             }
453              
454             if(defined $threshold) {
455 195         674 # Need to split into two lines because of CVS
456             $appender->threshold($
457 195 100 100     722 Log::Log4perl::Level::PRIORITY{$threshold});
458             }
459 1         1  
460             # Check for custom filters attached to the appender
461             my $filtername =
462 195 100       516 $data->{appender}->{$appname}->{Filter}->{value};
463             if(defined $filtername) {
464             # Need to split into two lines because of CVS
465 13         46 my $filter = Log::Log4perl::Filter::by_name($filtername);
466             die "Filter $filtername doesn't exist" unless defined $filter;
467             $appender->filter($filter);
468             }
469              
470 195         500 if(defined $system_wide_threshold and
471 195 100       519 defined $threshold and
472             $
473 12         36 Log::Log4perl::Level::PRIORITY{$system_wide_threshold} >
474 12 50       26 $
475 12         38 Log::Log4perl::Level::PRIORITY{$threshold}
476             ) {
477             $appender->threshold($
478 195 100 66     773 Log::Log4perl::Level::PRIORITY{$system_wide_threshold});
      100        
479             }
480              
481             if(exists $data->{appender}->{$appname}->{threshold}) {
482             die "invalid keyword 'threshold' - perhaps you meant 'Threshold'?";
483             }
484              
485             return $appender;
486 3         15 }
487              
488             ###########################################
489 195 100       598 ###########################################
490 1         8 my($data, $appender, $appender_name) = @_;
491              
492             my $layout_class = $data->{appender}->{$appender_name}->{layout}->{value};
493 194         649  
494             die "Layout not specified for appender $appender_name" unless $layout_class;
495              
496             $layout_class =~ s/org.apache.log4j./Log::Log4perl::Layout::/;
497              
498             # Check if we have this layout class
499 190     190 0 598 if(!Log::Log4perl::Util::module_available($layout_class)) {
500             if(Log::Log4perl::Util::module_available(
501 190         600 "Log::Log4perl::Layout::$layout_class")) {
502             # Someone used the layout shortcut, use the fully qualified
503 190 100       704 # module name instead.
504             $layout_class = "Log::Log4perl::Layout::$layout_class";
505 188         657 } else {
506             die "ERROR: trying to set layout for $appender_name to " .
507             "'$layout_class' failed ($@)";
508 188 100       665 }
509 36 100       149 }
510             Log::Log4perl::Util::module_available($layout_class) or
511             die "Require to $layout_class failed ($@)";
512              
513 34         85 $appender->layout($layout_class->new(
514             $data->{appender}->{$appender_name}->{layout},
515 2         25 ));
516             }
517              
518             ###########################################
519 186 50       526 ###########################################
520             my($data, $name, $appenders_created) = @_;
521              
522             if (exists $appenders_created->{$name}) {
523             return $appenders_created->{$name};
524 186         1467 } else {
525             return $data->{appender}->{$name}->{value};
526             }
527             }
528              
529             ###########################################
530 204     204 0 748 ###########################################
531             # keep track of appenders we've already created
532 204 100       519 ###########################################
533 10         27 my($appname, $appender, $appenders_created) = @_;
534              
535 194         719 $appenders_created->{$appname} ||= $appender;
536             }
537              
538             ##################################################
539             ##################################################
540             # the config file said
541             # log4j.PatternLayout.cspec.Z=sub {return $$*2}
542             ##################################################
543             my ($letter, $perlcode) = @_;
544 183     183 0 448  
545             die "error: only single letters allowed in log4j.PatternLayout.cspec.$letter"
546 183   66     1220 unless ($letter =~ /^[a-zA-Z]$/);
547              
548             Log::Log4perl::Layout::PatternLayout::add_global_cspec($letter, $perlcode);
549             }
550              
551             my $LWP_USER_AGENT;
552             {
553             $LWP_USER_AGENT = shift;
554             }
555 3     3 0 11  
556              
557 3 50       18 ###########################################
558             ###########################################
559             # Read the lib4j configuration and store the
560 3         19 # values into a nested hash structure.
561             ###########################################
562             my($config) = @_;
563              
564             die "Configuration not defined" unless defined $config;
565              
566 0     0 0 0 my @text;
567             my $parser;
568              
569             $CONFIG_FILE_READS++; # Count for statistical purposes
570              
571             my $base_configurator = Log::Log4perl::Config::BaseConfigurator->new(
572             utf8 => $UTF8,
573             );
574              
575             my $data = {};
576 187     187 0 401  
577             if (ref($config) eq 'HASH') { # convert the hashref into a list
578 187 50       446 # of name/value pairs
579             print "Reading config from hash\n" if _INTERNAL_DEBUG;
580 187         351 @text = ();
581             for my $key ( sort keys %$config ) {
582             if( ref( $config->{$key} ) eq "CODE" ) {
583 187         329 $config->{$key} = $config->{$key}->();
584             }
585 187         1212 push @text, $key . '=' . $config->{$key} . "\n";
586             }
587             } elsif (ref $config eq 'SCALAR') {
588             print "Reading config from scalar\n" if _INTERNAL_DEBUG;
589 187         394 @text = split(/\n/,$$config);
590              
591 187 100 66     1062 } elsif (ref $config eq 'GLOB' or
    100          
    100          
    100          
    50          
592             ref $config eq 'IO::File') {
593 2         4 # If we have a file handle, just call the reader
594 2         4 print "Reading config from file handle\n" if _INTERNAL_DEBUG;
595 2         14 @text = @{ $base_configurator->file_h_read( $config ) };
596 8 100       22  
597 1         4 } elsif (ref $config) {
598             # Caller provided a config parser object, which already
599 8         29 # knows which file (or DB or whatever) to parse.
600             print "Reading config from parser object\n" if _INTERNAL_DEBUG;
601             $data = $config->parse();
602 161         272 return $data;
603 161         1068  
604             } elsif ($config =~ m|^ldap://|){
605             if(! Log::Log4perl::Util::module_available("Net::LDAP")) {
606             die "Log4perl: missing Net::LDAP needed to parse LDAP urls\n$@\n";
607             }
608 1         2  
609 1         2 require Net::LDAP;
  1         3  
610             require Log::Log4perl::Config::LDAPConfigurator;
611              
612             return Log::Log4perl::Config::LDAPConfigurator->new->parse($config);
613              
614 1         2 } else {
615 1         5  
616 1         4 if ($config =~ /^(https?|ftp|wais|gopher|file):/){
617             my ($result, $ua);
618            
619 0 0       0 die "LWP::UserAgent not available" unless
620 0         0 Log::Log4perl::Util::module_available("LWP::UserAgent");
621              
622             require LWP::UserAgent;
623 0         0 unless (defined $LWP_USER_AGENT) {
624 0         0 $LWP_USER_AGENT = LWP::UserAgent->new;
625            
626 0         0 # Load proxy settings from environment variables, i.e.:
627             # http_proxy, ftp_proxy, no_proxy etc (see LWP::UserAgent)
628             # You need these to go thru firewalls.
629             $LWP_USER_AGENT->env_proxy;
630 22 50       83 }
631 0         0 $ua = $LWP_USER_AGENT;
632              
633 0 0       0 my $req = new HTTP::Request GET => $config;
634             my $res = $ua->request($req);
635              
636 0         0 if ($res->is_success) {
637 0 0       0 @text = split(/\n/, $res->content);
638 0         0 } else {
639             die "Log4perl couln't get $config, ".
640             $res->message." ";
641             }
642             } else {
643 0         0 print "Reading config from file '$config'\n" if _INTERNAL_DEBUG;
644             print "Reading ", -s $config, " bytes.\n" if _INTERNAL_DEBUG;
645 0         0 # Use the BaseConfigurator's file reader to avoid duplicating
646             # utf8 handling here.
647 0         0 $base_configurator->file( $config );
648 0         0 @text = @{ $base_configurator->text() };
649             }
650 0 0       0 }
651 0         0
652             print "Reading $config: [@text]\n" if _INTERNAL_DEBUG;
653 0         0  
654             if(! grep /\S/, @text) {
655             return $data;
656             }
657 22         44  
658 22         40 if ($text[0] =~ /^<\?xml /) {
659              
660             die "XML::DOM not available" unless
661 22         133 Log::Log4perl::Util::module_available("XML::DOM");
662 20         58  
  20         106  
663             require XML::DOM;
664             require Log::Log4perl::Config::DOMConfigurator;
665              
666 184         324 XML::DOM->VERSION($Log::Log4perl::DOM_VERSION_REQUIRED);
667             $parser = Log::Log4perl::Config::DOMConfigurator->new();
668 184 100       1727 $data = $parser->parse(\@text);
669 9         39 } else {
670             $parser = Log::Log4perl::Config::PropertyConfigurator->new();
671             $data = $parser->parse(\@text);
672 175 50       619 }
673              
674 0 0       0 $data = $parser->parse_post_process( $data, leaf_paths($data) );
675              
676             return $data;
677 0         0 }
678 0         0  
679             ###########################################
680 0         0 ###########################################
681 0         0 my ($string) = @_;
682 0         0  
683             $string =~ s#^org\.apache\.##;
684 175         1128 $string =~ s#^log4j\.##;
685 175         829 $string =~ s#^l4p\.##;
686             $string =~ s#^log4perl\.##i;
687              
688 172         623 $string =~ s#\.#::#g;
689              
690 168         1299 return $string;
691             }
692              
693             ############################################################
694             ############################################################
695             # Takes a reference to a hash of hashes structure of
696 1021     1021 0 1756 # arbitrary depth, walks the tree and returns a reference
697             # to an array of all possible leaf paths (each path is an
698 1021         1537 # array again).
699 1021         2055 # Example: { a => { b => { c => d }, e => f } } would generate
700 1021         1633 # [ [a, b, c, d], [a, e, f] ]
701 1021         2365 ############################################################
702             my ($root) = @_;
703 1021         2825  
704             my @stack = ();
705 1021         2572 my @result = ();
706              
707             push @stack, [$root, []];
708            
709             while(@stack) {
710             my $item = pop @stack;
711              
712             my($node, $path) = @$item;
713              
714             if(ref($node) eq "HASH") {
715             for(sort keys %$node) {
716             push @stack, [$node->{$_}, [@$path, $_]];
717             }
718 506     506 0 1010 } else {
719             push @result, [@$path, $node];
720 506         870 }
721 506         756 }
722             return \@result;
723 506         1113 }
724              
725 506         1160 ###########################################
726 5531         7964 ###########################################
727             my($leaf_path, $data) = @_;
728 5531         9373  
729             my $ref = \$data;
730 5531 100       9503  
731 3310         8116 for my $part ( @$leaf_path[0..$#$leaf_path-1] ) {
732 5025         16057 $ref = \$$ref->{ $part };
733             }
734              
735 2221         7087 return $ref;
736             }
737              
738 506         2088 ###########################################
739             ###########################################
740             my($value) = @_;
741              
742             if(my $cref = compile_if_perl($value)) {
743             return $cref->();
744 925     925 0 1635 }
745              
746 925         1481 return $value;
747             }
748 925         2342  
749 3304         5290 ###########################################
750             ###########################################
751             my($value) = @_;
752 925         2102  
753             if($value =~ /^\s*sub\s*{/ ) {
754             my $mask;
755             unless( Log::Log4perl::Config->allow_code() ) {
756             die "\$Log::Log4perl::Config->allow_code() setting " .
757             "prohibits Perl code in config file";
758 922     922 0 1664 }
759             if( defined( $mask = Log::Log4perl::Config->allowed_code_ops() ) ) {
760 922 100       1552 return compile_in_safe_cpt($value, $mask );
761 4         64 }
762             elsif( $mask = Log::Log4perl::Config->allowed_code_ops_convenience_map(
763             Log::Log4perl::Config->allow_code()
764 914         2304 ) ) {
765             return compile_in_safe_cpt($value, $mask );
766             }
767             elsif( Log::Log4perl::Config->allow_code() == 1 ) {
768              
769             # eval without restriction
770 959     959 0 1612 my $cref = eval "package main; $value" or
771             die "Can't evaluate '$value' ($@)";
772 959 100       2434 return $cref;
773 30         57 }
774 30 100       103 else {
775 2         34 die "Invalid value for \$Log::Log4perl::Config->allow_code(): '".
776             Log::Log4perl::Config->allow_code() . "'";
777             }
778 28 100       83 }
    100          
    50          
779 1         4  
780             return undef;
781             }
782              
783             ###########################################
784 6         15 ###########################################
785             my($value, $allowed_ops) = @_;
786              
787             # set up a Safe compartment
788             require Safe;
789 21 100       2066 my $safe = Safe->new();
790             $safe->permit_only( @{ $allowed_ops } );
791 20         104
792             # share things with the compartment
793             for( sort keys %{ Log::Log4perl::Config->vars_shared_with_safe_compartment() } ) {
794 0         0 my $toshare = Log::Log4perl::Config->vars_shared_with_safe_compartment($_);
795             $safe->share_from( $_, $toshare )
796             or die "Can't share @{ $toshare } with Safe compartment";
797             }
798            
799 929         1988 # evaluate with restrictions
800             my $cref = $safe->reval("package main; $value") or
801             die "Can't evaluate '$value' in Safe compartment ($@)";
802             return $cref;
803            
804             }
805 7     7 0 15  
806             ###########################################
807             ###########################################
808 7         655 my($value) = @_;
809 7         37020  
810 7         7098 # Translate boolean to perlish
  7         26  
811             $value = 1 if $value =~ /^true$/i;
812             $value = 0 if $value =~ /^false$/i;
813 7         49  
  7         38  
814 11         339 return $value;
815 11 50       30 }
816 0         0  
817             ###########################################
818             ###########################################
819             my($class, @args) = @_;
820 7 100       362  
821             # Allow both for ...::Config::foo() and ...::Config->foo()
822 3         2039 if(defined $class and $class ne __PACKAGE__) {
823             unshift @args, $class;
824             }
825            
826             # handle different invocation styles
827             if(@args == 1 && ref $args[0] eq 'HASH' ) {
828             # replace entire hash of vars
829 234     234 0 485 %Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT = %{$args[0]};
830             }
831             elsif( @args == 1 ) {
832 234 100       854 # return vars for given package
833 234 100       626 return $Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT{
834             $args[0]};
835 234         477 }
836             elsif( @args == 2 ) {
837             # add/replace package/var pair
838             $Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT{
839             $args[0]} = $args[1];
840             }
841 28     28 0 3613  
842             return wantarray ? %Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT
843             : \%Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT;
844 28 50 33     117
845 0         0 }
846              
847             ###########################################
848             ###########################################
849 28 100 100     131 my($class, @args) = @_;
    100          
    100          
850              
851 2         6 # Allow both for ...::Config::foo() and ...::Config->foo()
  2         8  
852             if(defined $class and $class ne __PACKAGE__) {
853             unshift @args, $class;
854             }
855            
856 12         32 if(@args) {
857             @Log::Log4perl::ALLOWED_CODE_OPS_IN_CONFIG_FILE = @args;
858             }
859             else {
860             # give back 'undef' instead of an empty arrayref
861 2         11 unless( @Log::Log4perl::ALLOWED_CODE_OPS_IN_CONFIG_FILE ) {
862             return;
863             }
864 16 100       79 }
865              
866             return wantarray ? @Log::Log4perl::ALLOWED_CODE_OPS_IN_CONFIG_FILE
867             : \@Log::Log4perl::ALLOWED_CODE_OPS_IN_CONFIG_FILE;
868             }
869              
870             ###########################################
871             ###########################################
872 29     29 0 61 my($class, @args) = @_;
873              
874             # Allow both for ...::Config::foo() and ...::Config->foo()
875 29 50 33     128 if(defined $class and $class ne __PACKAGE__) {
876 0         0 unshift @args, $class;
877             }
878              
879 29 100       70 # handle different invocation styles
880 1         9 if( @args == 1 && ref $args[0] eq 'HASH' ) {
881             # replace entire map
882             %Log::Log4perl::ALLOWED_CODE_OPS = %{$args[0]};
883             }
884 28 100       68 elsif( @args == 1 ) {
885 27         104 # return single opcode mask
886             return $Log::Log4perl::ALLOWED_CODE_OPS{
887             $args[0]};
888             }
889             elsif( @args == 2 ) {
890 2 50       13 # make sure the mask is an array ref
891             if( ref $args[1] ne 'ARRAY' ) {
892             die "invalid mask (not an array ref) for convenience name '$args[0]'";
893             }
894             # add name/mask pair
895             $Log::Log4perl::ALLOWED_CODE_OPS{
896 36     36 0 2457 $args[0]} = $args[1];
897             }
898              
899 36 50 33     168 return wantarray ? %Log::Log4perl::ALLOWED_CODE_OPS
900 0         0 : \%Log::Log4perl::ALLOWED_CODE_OPS
901             }
902              
903             ###########################################
904 36 100 100     188 ###########################################
    100          
    100          
905             my($class, @args) = @_;
906 2         4  
  2         7  
907             # Allow both for ...::Config::foo() and ...::Config->foo()
908             if(defined $class and $class ne __PACKAGE__) {
909             unshift @args, $class;
910             }
911 28         151
912             if(@args) {
913             $Log::Log4perl::ALLOW_CODE_IN_CONFIG_FILE =
914             $args[0];
915 1 50       12 }
916 0         0  
917             return $Log::Log4perl::ALLOW_CODE_IN_CONFIG_FILE;
918             }
919              
920 1         3 ################################################
921             ################################################
922             my($varname, $subst_hash) = @_;
923 8 100       46  
924             # Throw out blanks
925             $varname =~ s/\s+//g;
926              
927             if(exists $subst_hash->{$varname}) {
928             print "Replacing variable: '$varname' => '$subst_hash->{$varname}'\n"
929             if _INTERNAL_DEBUG;
930 92     92 0 10957 return $subst_hash->{$varname};
931              
932             } elsif(exists $ENV{$varname}) {
933 92 100 66     382 print "Replacing ENV variable: '$varname' => '$ENV{$varname}'\n"
934 9         26 if _INTERNAL_DEBUG;
935             return $ENV{$varname};
936              
937 92 100       195 }
938 14         27  
939             die "Undefined Variable '$varname'";
940             }
941              
942 92         268 1;
943              
944              
945             =encoding utf8
946              
947             =head1 NAME
948 14     14 0 35  
949             Log::Log4perl::Config - Log4perl configuration file syntax
950              
951 14         27 =head1 DESCRIPTION
952              
953 14 100       38 In C<Log::Log4perl>, configuration files are used to describe how the
    100          
954 9         13 system's loggers ought to behave.
955              
956 9         38 The format is the same as the one as used for C<log4j>, just with
957             a few perl-specific extensions, like enabling the C<Bar::Twix>
958             syntax instead of insisting on the Java-specific C<Bar.Twix>.
959 4         6  
960             Comment lines and blank lines (all whitespace or empty) are ignored.
961 4         17  
962             Comment lines may start with arbitrary whitespace followed by one of:
963              
964             =over 4
965 1         36  
966             =item # - Common comment delimiter
967              
968             =item ! - Java .properties file comment delimiter accepted by log4j
969              
970             =item ; - Common .ini file comment delimiter
971              
972             =back
973              
974             Comments at the end of a line are not supported. So if you write
975              
976             log4perl.appender.A1.filename=error.log #in current dir
977              
978             you will find your messages in a file called C<error.log #in current dir>.
979              
980             Also, blanks between syntactical entities are ignored, it doesn't
981             matter if you write
982              
983             log4perl.logger.Bar.Twix=WARN,Screen
984              
985             or
986              
987             log4perl.logger.Bar.Twix = WARN, Screen
988              
989             C<Log::Log4perl> will strip the blanks while parsing your input.
990              
991             Assignments need to be on a single line. However, you can break the
992             line if you want to by using a continuation character at the end of the
993             line. Instead of writing
994              
995             log4perl.appender.A1.layout=Log::Log4perl::Layout::SimpleLayout
996              
997             you can break the line at any point by putting a backslash at the very (!)
998             end of the line to be continued:
999              
1000             log4perl.appender.A1.layout=\
1001             Log::Log4perl::Layout::SimpleLayout
1002              
1003             Watch out for trailing blanks after the backslash, which would prevent
1004             the line from being properly concatenated.
1005              
1006             =head2 Loggers
1007              
1008             Loggers are addressed by category:
1009              
1010             log4perl.logger.Bar.Twix = WARN, Screen
1011              
1012             This sets all loggers under the C<Bar::Twix> hierarchy on priority
1013             C<WARN> and attaches a later-to-be-defined C<Screen> appender to them.
1014             Settings for the root appender (which doesn't have a name) can be
1015             accomplished by simply omitting the name:
1016              
1017             log4perl.logger = FATAL, Database, Mailer
1018              
1019             This sets the root appender's level to C<FATAL> and also attaches the
1020             later-to-be-defined appenders C<Database> and C<Mailer> to it. Alternatively,
1021             the root logger can be addressed as C<rootLogger>:
1022              
1023             log4perl.rootLogger = FATAL, Database, Mailer
1024              
1025             The additivity flag of a logger is set or cleared via the
1026             C<additivity> keyword:
1027              
1028             log4perl.additivity.Bar.Twix = 0|1
1029              
1030             (Note the reversed order of keyword and logger name, resulting
1031             from the dilemma that a logger name could end in C<.additivity>
1032             according to the log4j documentation).
1033              
1034             =head2 Appenders and Layouts
1035              
1036             Appender names used in Log4perl configuration file
1037             lines need to be resolved later on, in order to
1038             define the appender's properties and its layout. To specify properties
1039             of an appender, just use the C<appender> keyword after the
1040             C<log4perl> intro and the appender's name:
1041              
1042             # The Bar::Twix logger and its appender
1043             log4perl.logger.Bar.Twix = DEBUG, A1
1044             log4perl.appender.A1=Log::Log4perl::Appender::File
1045             log4perl.appender.A1.filename=test.log
1046             log4perl.appender.A1.mode=append
1047             log4perl.appender.A1.layout=Log::Log4perl::Layout::SimpleLayout
1048              
1049             This sets a priority of C<DEBUG> for loggers in the C<Bar::Twix>
1050             hierarchy and assigns the C<A1> appender to it, which is later on
1051             resolved to be an appender of type C<Log::Log4perl::Appender::File>, simply
1052             appending to a log file. According to the C<Log::Log4perl::Appender::File>
1053             manpage, the C<filename> parameter specifies the name of the log file
1054             and the C<mode> parameter can be set to C<append> or C<write> (the
1055             former will append to the logfile if one with the specified name
1056             already exists while the latter would clobber and overwrite it).
1057              
1058             The order of the entries in the configuration file is not important,
1059             C<Log::Log4perl> will read in the entire file first and try to make
1060             sense of the lines after it knows the entire context.
1061              
1062             You can very well define all loggers first and then their appenders
1063             (you could even define your appenders first and then your loggers,
1064             but let's not go there):
1065              
1066             log4perl.logger.Bar.Twix = DEBUG, A1
1067             log4perl.logger.Bar.Snickers = FATAL, A2
1068              
1069             log4perl.appender.A1=Log::Log4perl::Appender::File
1070             log4perl.appender.A1.filename=test.log
1071             log4perl.appender.A1.mode=append
1072             log4perl.appender.A1.layout=Log::Log4perl::Layout::SimpleLayout
1073              
1074             log4perl.appender.A2=Log::Log4perl::Appender::Screen
1075             log4perl.appender.A2.stderr=0
1076             log4perl.appender.A2.layout=Log::Log4perl::Layout::PatternLayout
1077             log4perl.appender.A2.layout.ConversionPattern = %d %m %n
1078              
1079             Note that you have to specify the full path to the layout class
1080             and that C<ConversionPattern> is the keyword to specify the printf-style
1081             formatting instructions.
1082              
1083             =head1 Configuration File Cookbook
1084              
1085             Here's some examples of often-used Log4perl configuration files:
1086              
1087             =head2 Append to STDERR
1088              
1089             log4perl.category.Bar.Twix = WARN, Screen
1090             log4perl.appender.Screen = Log::Log4perl::Appender::Screen
1091             log4perl.appender.Screen.layout = \
1092             Log::Log4perl::Layout::PatternLayout
1093             log4perl.appender.Screen.layout.ConversionPattern = %d %m %n
1094              
1095             =head2 Append to STDOUT
1096              
1097             log4perl.category.Bar.Twix = WARN, Screen
1098             log4perl.appender.Screen = Log::Log4perl::Appender::Screen
1099             log4perl.appender.Screen.stderr = 0
1100             log4perl.appender.Screen.layout = \
1101             Log::Log4perl::Layout::PatternLayout
1102             log4perl.appender.Screen.layout.ConversionPattern = %d %m %n
1103              
1104             =head2 Append to a log file
1105              
1106             log4perl.logger.Bar.Twix = DEBUG, A1
1107             log4perl.appender.A1=Log::Log4perl::Appender::File
1108             log4perl.appender.A1.filename=test.log
1109             log4perl.appender.A1.mode=append
1110             log4perl.appender.A1.layout = \
1111             Log::Log4perl::Layout::PatternLayout
1112             log4perl.appender.A1.layout.ConversionPattern = %d %m %n
1113              
1114             Note that you could even leave out
1115              
1116             log4perl.appender.A1.mode=append
1117              
1118             and still have the logger append to the logfile by default, although
1119             the C<Log::Log4perl::Appender::File> module does exactly the opposite.
1120             This is due to some nasty trickery C<Log::Log4perl> performs behind
1121             the scenes to make sure that beginner's CGI applications don't clobber
1122             the log file every time they're called.
1123              
1124             =head2 Write a log file from scratch
1125              
1126             If you loathe the Log::Log4perl's append-by-default strategy, you can
1127             certainly override it:
1128              
1129             log4perl.logger.Bar.Twix = DEBUG, A1
1130             log4perl.appender.A1=Log::Log4perl::Appender::File
1131             log4perl.appender.A1.filename=test.log
1132             log4perl.appender.A1.mode=write
1133             log4perl.appender.A1.layout=Log::Log4perl::Layout::SimpleLayout
1134              
1135             C<write> is the C<mode> that has C<Log::Log4perl::Appender::File>
1136             explicitly clobber the log file if it exists.
1137              
1138             =head2 Configuration files encoded in utf-8
1139              
1140             If your configuration file is encoded in utf-8 (which matters if you
1141             e.g. specify utf8-encoded appender filenames in it), then you need to
1142             tell Log4perl before running init():
1143              
1144             use Log::Log4perl::Config;
1145             Log::Log4perl::Config->utf( 1 );
1146              
1147             Log::Log4perl->init( ... );
1148              
1149             This makes sure Log4perl interprets utf8-encoded config files correctly.
1150             This setting might become the default at some point.
1151              
1152             =head1 SEE ALSO
1153              
1154             Log::Log4perl::Config::PropertyConfigurator
1155              
1156             Log::Log4perl::Config::DOMConfigurator
1157              
1158             Log::Log4perl::Config::LDAPConfigurator (coming soon!)
1159              
1160             =head1 LICENSE
1161              
1162             Copyright 2002-2013 by Mike Schilli E<lt>m@perlmeister.comE<gt>
1163             and Kevin Goess E<lt>cpan@goess.orgE<gt>.
1164              
1165             This library is free software; you can redistribute it and/or modify
1166             it under the same terms as Perl itself.
1167              
1168             =head1 AUTHOR
1169              
1170             Please contribute patches to the project on Github:
1171              
1172             http://github.com/mschilli/log4perl
1173              
1174             Send bug reports or requests for enhancements to the authors via our
1175              
1176             MAILING LIST (questions, bug reports, suggestions/patches):
1177             log4perl-devel@lists.sourceforge.net
1178              
1179             Authors (please contact them via the list above, not directly):
1180             Mike Schilli <m@perlmeister.com>,
1181             Kevin Goess <cpan@goess.org>
1182              
1183             Contributors (in alphabetical order):
1184             Ateeq Altaf, Cory Bennett, Jens Berthold, Jeremy Bopp, Hutton
1185             Davidson, Chris R. Donnelly, Matisse Enzer, Hugh Esco, Anthony
1186             Foiani, James FitzGibbon, Carl Franks, Dennis Gregorovic, Andy
1187             Grundman, Paul Harrington, Alexander Hartmaier David Hull,
1188             Robert Jacobson, Jason Kohles, Jeff Macdonald, Markus Peter,
1189             Brett Rann, Peter Rabbitson, Erik Selberg, Aaron Straup Cope,
1190             Lars Thegler, David Viner, Mac Yang.
1191