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   1040 use strict;
  70         206  
5 70     70   299 use warnings;
  70         117  
  70         1286  
6 70     70   293  
  70         160  
  70         1721  
7             use Log::Log4perl::Logger;
8 70     70   361 use Log::Log4perl::Level;
  70         135  
  70         1863  
9 70     70   371 use Log::Log4perl::Config::PropertyConfigurator;
  70         159  
  70         467  
10 70     70   26679 use Log::Log4perl::JavaMap;
  70         164  
  70         1723  
11 70     70   26309 use Log::Log4perl::Filter;
  70         162  
  70         1937  
12 70     70   390 use Log::Log4perl::Filter::Boolean;
  70         128  
  70         1302  
13 70     70   26018 use Log::Log4perl::Config::Watch;
  70         164  
  70         1630  
14 70     70   26839  
  70         188  
  70         2176  
15             use constant _INTERNAL_DEBUG => 0;
16 70     70   426  
  70         138  
  70         296085  
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 894 undef $WATCHER; # just in case there's a one left over (e.g. test cases)
33              
34 178         295 return _init(@_);
35             }
36 178         505  
37             ###########################################
38             ###########################################
39             my( $class, $flag ) = @_;
40              
41             $UTF8 = $flag if defined $flag;
42 1     1 0 591  
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 32 $config = $WATCHER->file();
59             if(defined $Log::Log4perl::Config::Watch::SIGNAL_CAUGHT) {
60             $delay = $WATCHER->signal();
61             } else {
62 9 100       30 $delay = $WATCHER->check_interval();
63 6         24 }
64 6 100       21 }
65 1         2  
66             print "init_and_watch ($config-$delay). Resetting.\n" if _INTERNAL_DEBUG;
67 5         19  
68             Log::Log4perl::Logger->reset();
69              
70             defined ($delay) or $delay = $DEFAULT_WATCH_DELAY;
71 9         20  
72             if (ref $config) {
73 9         59 die "Log4perl can only watch a file, not a string of " .
74             "configuration information";
75 9 50       29 }elsif ($config =~ m!^(https?|ftp|wais|gopher|file):!){
76             die "Log4perl can only watch a file, not a url like $config";
77 9 50       60 }
    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       53 );
85 2         11 } else {
86             $WATCHER = Log::Log4perl::Config::Watch->new(
87             file => $config,
88             check_interval => $delay,
89             l4p_internal => 1,
90             );
91 7         60 }
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       31 eval { _init($class, $config); };
99 1 50       5  
100 1         2 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         36  
104             warn "Loading new config failed, reverted to old one\n";
105 9 50       44 }
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   460 print "Calling _init\n" if _INTERNAL_DEBUG;
117              
118 187         338 #keep track so we don't create the same one twice
119             my %appenders_created = ();
120 187         301  
121             #some appenders need to run certain subroutines right at the
122 187         251 #end of the configuration phase, when all settings are in place.
123             my @post_config_subs = ();
124              
125 187         299 # 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         305 # 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       720 }
146              
147 178         283 my @loggers = ();
148             my %filter_names = ();
149              
150             my $system_wide_threshold;
151              
152             # Autocorrect the rootlogger/rootLogger typo
153 178         336 if(exists $data->{rootlogger} and
154 178         304 ! exists $data->{rootLogger}) {
155             $data->{rootLogger} = $data->{rootlogger};
156 178         280 }
157              
158             # Find all logger definitions in the conf file. Start
159 178 100 66     606 # with root loggers.
160             if(exists $data->{rootLogger}) {
161 1         2 $LOGGERS_DEFINED++;
162             push @loggers, ["", $data->{rootLogger}->{value}];
163             }
164            
165             # Check if we've got a system-wide threshold setting
166 178 100       462 if(exists $data->{threshold}) {
167 27         49 # yes, we do.
168 27         74 $system_wide_threshold = $data->{threshold}->{value};
169             }
170              
171             if (exists $data->{oneMessagePerAppender}){
172 178 100       455 $Log::Log4perl::one_message_per_appender =
173             $data->{oneMessagePerAppender}->{value};
174 4         6 }
175              
176             if(exists $data->{utcDateTimes}) {
177 178 100       451 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       418 }
183 2         11  
184             # Boolean filters
185             my %boolean_filters = ();
186              
187 2         5 # 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         300  
192             if(exists $data->{$key}) {
193              
194             for my $path (@{leaf_paths($data->{$key})}) {
195              
196 178         381 print "Path before: @$path\n" if _INTERNAL_DEBUG;
197              
198 889 100       1806 my $value = boolean_to_perlish(pop @$path);
199              
200 162         276 pop @$path; # Drop the 'value' keyword part
  162         413  
201              
202 223         292 if($key eq "additivity") {
203             # This isn't a logger but an additivity setting.
204 223         598 # Save it in a hash under the logger's name for later.
205             $additivity{join('.', @$path)} = $value;
206 223         480  
207             #a global user-defined conversion specifier (cspec)
208 223 100       734 }elsif ($key eq "PatternLayout"){
    100          
    100          
209             &add_global_cspec(@$path[-1], $value);
210              
211 3         12 }elsif ($key eq "filter"){
212             print "Found entry @$path\n" if _INTERNAL_DEBUG;
213             $filter_names{@$path[0]}++;
214             } else {
215 3         18  
216             if (ref($value) eq "ARRAY") {
217             die "Multiple definitions of logger ".join('.',@$path)." in log4perl config";
218 52         51 }
219 52         91  
220             # This is a regular logger
221             $LOGGERS_DEFINED++;
222 165 50       420 push @loggers, [join('.', @$path), $value];
223 0         0 }
224             }
225             }
226             }
227 165         273  
228 165         662 # 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         541 if($data->{filter}->{$filter_name}->{value} eq
236             "Log::Log4perl::Filter::Boolean") {
237 22         24 print "Boolean filter ($filter_name)\n" if _INTERNAL_DEBUG;
238             $boolean_filters{$filter_name}++;
239             next;
240             }
241 22 100       43  
242             my $type = $data->{filter}->{$filter_name}->{value};
243 3         3 if(my $code = compile_if_perl($type)) {
244 3         5 $type = $code;
245 3         5 }
246            
247             print "Filter $filter_name is of type $type\n" if _INTERNAL_DEBUG;
248 19         28  
249 19 100       25 my $filter;
250 4         6  
251             if(ref($type) eq "CODE") {
252             # Subroutine - map into generic Log::Log4perl::Filter class
253 18         22 $filter = Log::Log4perl::Filter->new($filter_name, $type);
254             } else {
255 18         20 # Filter class
256             die "Filter class '$type' doesn't exist" unless
257 18 100       55 Log::Log4perl::Util::module_available($type);
258             eval "require $type" or die "Require of $type failed ($!)";
259 4         17  
260             # Invoke with all defined parameter
261             # key/values (except the key 'value' which is the entry
262 14 100       37 # for the class)
263             $filter = $type->new(name => $filter_name,
264 13 50       674 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         121 }
271 40         66  
272 13         38 # Initialize boolean filters (they need the other filters to be
  13         56  
273             # initialized to be able to compile their logic)
274             for my $name (sort keys %boolean_filters) {
275 16         65 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         422 $filter->register();
281 3         6 }
282 3 50       9  
283 3         16 for (@loggers) {
284             my($name, $value) = @$_;
285              
286 3         14 my $logger = Log::Log4perl::Logger->get_logger($name);
287             my ($level, @appnames) = split /\s*,\s*/, $value;
288              
289 174         373 $logger->level(
290 188         429 Log::Log4perl::Level::to_priority($level),
291             'dont_reset_all');
292 188         858  
293 188         1211 if(exists $additivity{$name}) {
294             $logger->additivity($additivity{$name}, 1);
295 188         752 }
296              
297             for my $appname (@appnames) {
298              
299 187 100       493 my $appender = create_appender_instance(
300 3         10 $data, $appname, \%appenders_created, \@post_config_subs,
301             $system_wide_threshold);
302              
303 187         367 $logger->add_appender($appender, 'dont_reset_all');
304             set_appender_by_name($appname, $appender, \%appenders_created);
305 193         744 }
306             }
307              
308             #run post_config subs
309 183         804 for(@post_config_subs) {
310 183         487 $_->();
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         491  
316 11         35 #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         585 "$CONFIG_INTEGRITY_ERROR";
321             }
322              
323 163 100 100     804 # Successful init(), save config for later
324             $OLD_CONFIG = $data;
325 5         112  
326             $Log::Log4perl::Logger::INITIALIZED = 1;
327             }
328              
329             ##################################################
330 163         785 ##################################################
331             if(! $LOGGERS_DEFINED) {
332 163         892 $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 457 return 0;
339 4         6 }
340 4         11  
341             return 1;
342             }
343 150 100       516  
344 1         3 ##################################################
345 1         3 ##################################################
346             my($data, $appname, $appenders_created, $post_config_subs,
347             $system_wide_threshold) = @_;
348 149         484  
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 617 my $appender;
355              
356             if (ref $appenderclass) {
357 204         622 $appender = $appenderclass;
358             } else {
359             die "ERROR: you didn't tell me how to " .
360 204         303 "implement your appender '$appname'"
361             unless $appenderclass;
362 204         303  
363             if (Log::Log4perl::JavaMap::translate($appenderclass)){
364 204 100       511 # It's Java. Try to map
365 10         20 print "Trying to map Java $appname\n" if _INTERNAL_DEBUG;
366             $appender = Log::Log4perl::JavaMap::get($appname,
367 194 100       790 $data->{appender}->{$appname});
368              
369             }else{
370             # It's Perl
371 193 100       694 my @params = grep { $_ ne "layout" and
372             $_ ne "value"
373 13         25 } sort keys %{$data->{appender}->{$appname}};
374            
375 13         169 my %param = ();
376             foreach my $pname (@params){
377             #this could be simple value like
378             #{appender}{myAppender}{file}{value} => 'log.txt'
379 544 100       1873 #or a structure like
380             #{appender}{myAppender}{login} =>
381 180         320 # { name => {value => 'bob'},
  180         764  
382             # pwd => {value => 'xxx'},
383 180         359 # }
384 180         347 #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       422 {$_}
394             {value}}
395             sort keys %{$data->{appender}
396 192         443 {$appname}
397             {$pname}}
398             };
399             }
400            
401             }
402 14         41  
403 5         10 my $depends_on = [];
404            
405 5         20 $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         336 );
412            
413 180         1076 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         544 # 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         41 # method. This is used by a composite appender which needs
431 11 50       27 # to make sure all of its appender-refs are available when
432 11         52 # 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         53 # Check for appender thresholds
446             my $threshold =
447             $data->{appender}->{$appname}->{Threshold}->{value};
448              
449             if(defined $system_wide_threshold and
450 201 100       584 !defined $threshold) {
451             $threshold = $system_wide_threshold;
452             }
453              
454             if(defined $threshold) {
455 195         629 # Need to split into two lines because of CVS
456             $appender->threshold($
457 195 100 100     627 Log::Log4perl::Level::PRIORITY{$threshold});
458             }
459 1         2  
460             # Check for custom filters attached to the appender
461             my $filtername =
462 195 100       481 $data->{appender}->{$appname}->{Filter}->{value};
463             if(defined $filtername) {
464             # Need to split into two lines because of CVS
465 13         37 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         478 if(defined $system_wide_threshold and
471 195 100       523 defined $threshold and
472             $
473 12         24 Log::Log4perl::Level::PRIORITY{$system_wide_threshold} >
474 12 50       22 $
475 12         25 Log::Log4perl::Level::PRIORITY{$threshold}
476             ) {
477             $appender->threshold($
478 195 100 66     645 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         6 }
487              
488             ###########################################
489 195 100       512 ###########################################
490 1         9 my($data, $appender, $appender_name) = @_;
491              
492             my $layout_class = $data->{appender}->{$appender_name}->{layout}->{value};
493 194         543  
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 481 if(!Log::Log4perl::Util::module_available($layout_class)) {
500             if(Log::Log4perl::Util::module_available(
501 190         549 "Log::Log4perl::Layout::$layout_class")) {
502             # Someone used the layout shortcut, use the fully qualified
503 190 100       627 # module name instead.
504             $layout_class = "Log::Log4perl::Layout::$layout_class";
505 188         599 } else {
506             die "ERROR: trying to set layout for $appender_name to " .
507             "'$layout_class' failed ($@)";
508 188 100       656 }
509 36 100       193 }
510             Log::Log4perl::Util::module_available($layout_class) or
511             die "Require to $layout_class failed ($@)";
512              
513 34         138 $appender->layout($layout_class->new(
514             $data->{appender}->{$appender_name}->{layout},
515 2         24 ));
516             }
517              
518             ###########################################
519 186 50       468 ###########################################
520             my($data, $name, $appenders_created) = @_;
521              
522             if (exists $appenders_created->{$name}) {
523             return $appenders_created->{$name};
524 186         1351 } else {
525             return $data->{appender}->{$name}->{value};
526             }
527             }
528              
529             ###########################################
530 204     204 0 651 ###########################################
531             # keep track of appenders we've already created
532 204 100       496 ###########################################
533 10         21 my($appname, $appender, $appenders_created) = @_;
534              
535 194         622 $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 412  
545             die "error: only single letters allowed in log4j.PatternLayout.cspec.$letter"
546 183   66     1103 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 10  
556              
557 3 50       12 ###########################################
558             ###########################################
559             # Read the lib4j configuration and store the
560 3         14 # 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 351  
577             if (ref($config) eq 'HASH') { # convert the hashref into a list
578 187 50       410 # of name/value pairs
579             print "Reading config from hash\n" if _INTERNAL_DEBUG;
580 187         329 @text = ();
581             for my $key ( sort keys %$config ) {
582             if( ref( $config->{$key} ) eq "CODE" ) {
583 187         333 $config->{$key} = $config->{$key}->();
584             }
585 187         1119 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         344 @text = split(/\n/,$$config);
590              
591 187 100 66     965 } 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         9 print "Reading config from file handle\n" if _INTERNAL_DEBUG;
595 2         12 @text = @{ $base_configurator->file_h_read( $config ) };
596 8 100       17  
597 1         3 } elsif (ref $config) {
598             # Caller provided a config parser object, which already
599 8         23 # 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         233 return $data;
603 161         971  
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         2  
610             require Log::Log4perl::Config::LDAPConfigurator;
611              
612             return Log::Log4perl::Config::LDAPConfigurator->new->parse($config);
613              
614 1         4 } else {
615 1         4  
616 1         3 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       66 }
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         28  
658 22         35 if ($text[0] =~ /^<\?xml /) {
659              
660             die "XML::DOM not available" unless
661 22         80 Log::Log4perl::Util::module_available("XML::DOM");
662 20         51  
  20         79  
663             require XML::DOM;
664             require Log::Log4perl::Config::DOMConfigurator;
665              
666 184         314 XML::DOM->VERSION($Log::Log4perl::DOM_VERSION_REQUIRED);
667             $parser = Log::Log4perl::Config::DOMConfigurator->new();
668 184 100       1496 $data = $parser->parse(\@text);
669 9         30 } else {
670             $parser = Log::Log4perl::Config::PropertyConfigurator->new();
671             $data = $parser->parse(\@text);
672 175 50       582 }
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         991 $string =~ s#^log4j\.##;
685 175         739 $string =~ s#^l4p\.##;
686             $string =~ s#^log4perl\.##i;
687              
688 172         599 $string =~ s#\.#::#g;
689              
690 168         1092 return $string;
691             }
692              
693             ############################################################
694             ############################################################
695             # Takes a reference to a hash of hashes structure of
696 1021     1021 0 1532 # arbitrary depth, walks the tree and returns a reference
697             # to an array of all possible leaf paths (each path is an
698 1021         1329 # array again).
699 1021         1674 # Example: { a => { b => { c => d }, e => f } } would generate
700 1021         1309 # [ [a, b, c, d], [a, e, f] ]
701 1021         2008 ############################################################
702             my ($root) = @_;
703 1021         2705  
704             my @stack = ();
705 1021         2102 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 894 } else {
719             push @result, [@$path, $node];
720 506         797 }
721 506         653 }
722             return \@result;
723 506         952 }
724              
725 506         1015 ###########################################
726 5531         6708 ###########################################
727             my($leaf_path, $data) = @_;
728 5531         7197  
729             my $ref = \$data;
730 5531 100       7770  
731 3310         6798 for my $part ( @$leaf_path[0..$#$leaf_path-1] ) {
732 5025         13175 $ref = \$$ref->{ $part };
733             }
734              
735 2221         5739 return $ref;
736             }
737              
738 506         1892 ###########################################
739             ###########################################
740             my($value) = @_;
741              
742             if(my $cref = compile_if_perl($value)) {
743             return $cref->();
744 925     925 0 1477 }
745              
746 925         1199 return $value;
747             }
748 925         1994  
749 3304         4341 ###########################################
750             ###########################################
751             my($value) = @_;
752 925         1672  
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 1433 }
759             if( defined( $mask = Log::Log4perl::Config->allowed_code_ops() ) ) {
760 922 100       1343 return compile_in_safe_cpt($value, $mask );
761 4         54 }
762             elsif( $mask = Log::Log4perl::Config->allowed_code_ops_convenience_map(
763             Log::Log4perl::Config->allow_code()
764 914         1929 ) ) {
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 1274 my $cref = eval "package main; $value" or
771             die "Can't evaluate '$value' ($@)";
772 959 100       1997 return $cref;
773 30         45 }
774 30 100       79 else {
775 2         63 die "Invalid value for \$Log::Log4perl::Config->allow_code(): '".
776             Log::Log4perl::Config->allow_code() . "'";
777             }
778 28 100       78 }
    100          
    50          
779 1         4  
780             return undef;
781             }
782              
783             ###########################################
784 6         16 ###########################################
785             my($value, $allowed_ops) = @_;
786              
787             # set up a Safe compartment
788             require Safe;
789 21 100       1957 my $safe = Safe->new();
790             $safe->permit_only( @{ $allowed_ops } );
791 20         82
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         1728 # 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         1797 my($value) = @_;
809 7         32689  
810 7         5927 # Translate boolean to perlish
  7         24  
811             $value = 1 if $value =~ /^true$/i;
812             $value = 0 if $value =~ /^false$/i;
813 7         42  
  7         33  
814 11         249 return $value;
815 11 50       26 }
816 0         0  
817             ###########################################
818             ###########################################
819             my($class, @args) = @_;
820 7 100       302  
821             # Allow both for ...::Config::foo() and ...::Config->foo()
822 3         1711 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 441 %Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT = %{$args[0]};
830             }
831             elsif( @args == 1 ) {
832 234 100       716 # return vars for given package
833 234 100       551 return $Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT{
834             $args[0]};
835 234         415 }
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 2930  
842             return wantarray ? %Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT
843             : \%Log::Log4perl::VARS_SHARED_WITH_SAFE_COMPARTMENT;
844 28 50 33     98
845 0         0 }
846              
847             ###########################################
848             ###########################################
849 28 100 100     103 my($class, @args) = @_;
    100          
    100          
850              
851 2         3 # Allow both for ...::Config::foo() and ...::Config->foo()
  2         7  
852             if(defined $class and $class ne __PACKAGE__) {
853             unshift @args, $class;
854             }
855            
856 12         26 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         7 unless( @Log::Log4perl::ALLOWED_CODE_OPS_IN_CONFIG_FILE ) {
862             return;
863             }
864 16 100       78 }
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 68 my($class, @args) = @_;
873              
874             # Allow both for ...::Config::foo() and ...::Config->foo()
875 29 50 33     135 if(defined $class and $class ne __PACKAGE__) {
876 0         0 unshift @args, $class;
877             }
878              
879 29 100       66 # handle different invocation styles
880 1         3 if( @args == 1 && ref $args[0] eq 'HASH' ) {
881             # replace entire map
882             %Log::Log4perl::ALLOWED_CODE_OPS = %{$args[0]};
883             }
884 28 100       64 elsif( @args == 1 ) {
885 27         124 # return single opcode mask
886             return $Log::Log4perl::ALLOWED_CODE_OPS{
887             $args[0]};
888             }
889             elsif( @args == 2 ) {
890 2 50       6 # 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 2001 $args[0]} = $args[1];
897             }
898              
899 36 50 33     145 return wantarray ? %Log::Log4perl::ALLOWED_CODE_OPS
900 0         0 : \%Log::Log4perl::ALLOWED_CODE_OPS
901             }
902              
903             ###########################################
904 36 100 100     143 ###########################################
    100          
    100          
905             my($class, @args) = @_;
906 2         4  
  2         6  
907             # Allow both for ...::Config::foo() and ...::Config->foo()
908             if(defined $class and $class ne __PACKAGE__) {
909             unshift @args, $class;
910             }
911 28         125
912             if(@args) {
913             $Log::Log4perl::ALLOW_CODE_IN_CONFIG_FILE =
914             $args[0];
915 1 50       4 }
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       63  
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 9463 return $subst_hash->{$varname};
931              
932             } elsif(exists $ENV{$varname}) {
933 92 100 66     311 print "Replacing ENV variable: '$varname' => '$ENV{$varname}'\n"
934 9         22 if _INTERNAL_DEBUG;
935             return $ENV{$varname};
936              
937 92 100       165 }
938 14         24  
939             die "Undefined Variable '$varname'";
940             }
941              
942 92         207 1;
943              
944              
945             =encoding utf8
946              
947             =head1 NAME
948 14     14 0 32  
949             Log::Log4perl::Config - Log4perl configuration file syntax
950              
951 14         18 =head1 DESCRIPTION
952              
953 14 100       31 In C<Log::Log4perl>, configuration files are used to describe how the
    100          
954 9         11 system's loggers ought to behave.
955              
956 9         29 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         15  
962             Comment lines may start with arbitrary whitespace followed by one of:
963              
964             =over 4
965 1         30  
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