File Coverage

blib/lib/XML/SAX/ParserFactory.pm
Criterion Covered Total %
statement 67 68 98.5
branch 20 22 90.9
condition n/a
subroutine 9 9 100.0
pod 0 3 0.0
total 96 102 94.1


line stmt bran cond sub pod time code
1             # $Id$
2              
3             package XML::SAX::ParserFactory;
4              
5 13     13   8105 use strict;
  13         24  
  13         588  
6 13     13   87 use vars qw($VERSION);
  13         23  
  13         993  
7              
8             $VERSION = '1.01';
9              
10 13     13   837 use Symbol qw(gensym);
  13         1007  
  13         629  
11 13     13   587 use XML::SAX;
  13         22  
  13         408  
12 13     13   381283 use XML::SAX::Exception;
  13         27555  
  13         11639  
13              
14             sub new {
15 10     10 0 683 my $class = shift;
16 10         22 my %params = @_; # TODO : Fix this in spec.
17 10         27 my $self = bless \%params, $class;
18 10         49 $self->{KnownParsers} = XML::SAX->parsers();
19 10         31 return $self;
20             }
21              
22             sub parser {
23 12     12 0 927 my $self = shift;
24 12         23 my @parser_params = @_;
25 12 100       36 if (!ref($self)) {
26 8         31 $self = $self->new();
27             }
28            
29 12         35 my $parser_class = $self->_parser_class();
30              
31 11         24 my $version = '';
32 11 100       47 if ($parser_class =~ s/\s*\(([\d\.]+)\)\s*$//) {
33 1         3 $version = " $1";
34             }
35              
36 11 100       118 if (!$parser_class->can('new')) {
37 1         103 eval "require $parser_class $version;";
38 1 50       150 die $@ if $@;
39             }
40              
41 11         53 return $parser_class->new(@parser_params);
42             }
43              
44             sub require_feature {
45 2     2 0 488 my $self = shift;
46 2         5 my ($feature) = @_;
47 2         7 $self->{RequiredFeatures}{$feature}++;
48 2         7 return $self;
49             }
50              
51             sub _parser_class {
52 12     12   20 my $self = shift;
53              
54             # First try ParserPackage
55 12 100       31 if ($XML::SAX::ParserPackage) {
56 2         4 return $XML::SAX::ParserPackage;
57             }
58              
59             # Now check if required/preferred is there
60 10 100       34 if ($self->{RequiredFeatures}) {
61 2         3 my %required = %{$self->{RequiredFeatures}};
  2         11  
62             # note - we never go onto the next try (ParserDetails.ini),
63             # because if we can't provide the requested feature
64             # we need to throw an exception.
65 2         5 PARSER:
66 2         4 foreach my $parser (reverse @{$self->{KnownParsers}}) {
67 2         7 foreach my $feature (keys %required) {
68 3 100       10 if (!exists $parser->{Features}{$feature}) {
69 1         5 next PARSER;
70             }
71             }
72             # got here - all features must exist!
73 1         4 return $parser->{Name};
74             }
75             # TODO : should this be NotSupported() ?
76             throw XML::SAX::Exception (
77 1         10 Message => "Unable to provide required features",
78             );
79             }
80              
81             # Next try SAX.ini
82 8         19 for my $dir (@INC) {
83 93         250 my $fh = gensym();
84 93 100       8264 if (open($fh, "$dir/SAX.ini")) {
85 5         38 my $param_list = XML::SAX->_parse_ini_file($fh);
86 5         13 my $params = $param_list->[0]->{Features};
87 5 100       17 if ($params->{ParserPackage}) {
88 2         41 return $params->{ParserPackage};
89             }
90             else {
91             # we have required features (or nothing?)
92 3         13 PARSER:
93 3         5 foreach my $parser (reverse @{$self->{KnownParsers}}) {
94 4         12 foreach my $feature (keys %$params) {
95 4 100       25 if (!exists $parser->{Features}{$feature}) {
96 2         11 next PARSER;
97             }
98             }
99 2         43 return $parser->{Name};
100             }
101 1         8 XML::SAX->do_warn("Unable to provide SAX.ini required features. Using fallback\n");
102             }
103 1         18 last; # stop after first INI found
104             }
105             }
106              
107 4 50       9 if (@{$self->{KnownParsers}}) {
  4         19  
108 4         12 return $self->{KnownParsers}[-1]{Name};
109             }
110             else {
111 0           return "XML::SAX::PurePerl"; # backup plan!
112             }
113             }
114              
115             1;
116             __END__