File Coverage

blib/lib/Mirror/URI.pm
Criterion Covered Total %
statement 107 115 93.0
branch 17 30 56.6
condition 2 6 33.3
subroutine 32 32 100.0
pod 0 16 0.0
total 158 199 79.4


line stmt bran cond sub pod time code
1             package Mirror::URI;
2              
3             # Abstract base module to allow easy extension to other file formats.
4              
5 4     4   1637 use 5.00503;
  4         16  
  4         157  
6 4     4   22 use strict;
  4         7  
  4         121  
7 4     4   31 use Carp ();
  4         9  
  4         71  
8 4     4   18 use File::Spec ();
  4         6  
  4         60  
9 4     4   4290 use Time::HiRes ();
  4         8725  
  4         135  
10 4     4   3136 use Time::Local ();
  4         6444  
  4         84  
11 4     4   3109 use URI ();
  4         23400  
  4         156  
12 4     4   4853 use URI::file ();
  4         24915  
  4         94  
13 4     4   3448 use URI::http ();
  4         9418  
  4         98  
14 4     4   28454 use Params::Util qw{ _STRING _POSINT _ARRAY0 _INSTANCE };
  4         16081  
  4         524  
15 4     4   2797 use LWP::Simple ();
  4         290631  
  4         113  
16              
17             # Time values have an extra 5 minute fudge factor
18 4     4   33 use constant ONE_DAY => 86700;
  4         10  
  4         263  
19 4     4   26 use constant TWO_DAYS => 172800;
  4         8  
  4         177  
20 4     4   20 use constant THIRTY_DAYS => 2592000;
  4         7  
  4         162  
21              
22 4     4   26 use vars qw{$VERSION};
  4         8  
  4         256  
23             BEGIN {
24 4     4   6229 $VERSION = '0.04_01';
25             }
26              
27              
28              
29              
30              
31             #####################################################################
32             # Constructor and Accessors
33              
34             sub new {
35 5     5 0 13 my $class = shift;
36 5         43 my $self = bless { @_ }, $class;
37              
38             # Clean up params
39 5         29 $self->{class} = $class;
40 5         35 $self->{valid} = !! $self->valid;
41 5 100       16 if ( $self->valid ) {
42 2 50       17 if ( _STRING($self->master) ) {
43 2         7 $self->{master} = URI->new( $self->master );
44             }
45 2 50       364 unless ( _INSTANCE($self->master, 'URI') ) {
46 0         0 Carp::croak("Missing or invalid 'master' value");
47             }
48 2 50 33     104 if ( _STRING($self->{timestamp}) and ! _POSINT($self->{timestamp}) ) {
49 2 50       43 unless ( $self->{timestamp} =~ /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z$/ ) {
50 0         0 Carp::croak("Invalid timestamp format");
51             }
52 2         23 $self->{timestamp} = Time::Local::timegm( $6, $5, $4, $3, $2 - 1, $1 );
53             }
54 2         100 my $mirrors = $self->{mirrors};
55 2 50       11 unless ( _ARRAY0($mirrors) ) {
56 0         0 croak("Invalid mirror list");
57             }
58 2         11 foreach my $i ( 0 .. $#$mirrors ) {
59 15 50       746 next unless _STRING($mirrors->[$i]);
60 15         43 $mirrors->[$i] = URI->new( $mirrors->[$i] );
61             }
62             }
63              
64 5         160 return $self;
65             }
66              
67             sub class {
68 2     2 0 16 $_[0]->{class};
69             }
70              
71             sub version {
72 3     3 0 756 $_[0]->{version};
73             }
74              
75             sub uri {
76 2     2 0 14 $_[0]->{uri};
77             }
78              
79             sub name {
80 4     4 0 518 $_[0]->{name};
81             }
82              
83             sub master {
84 12     12 0 409 $_[0]->{master};
85             }
86              
87             sub timestamp {
88 2     2 0 10 $_[0]->{timestamp};
89             }
90              
91             sub mirrors {
92 1     1 0 3 return ( @{ $_[0]->{mirrors} } );
  1         7  
93             }
94              
95             sub valid {
96 13     13 0 6451 $_[0]->{valid};
97             }
98              
99             sub lastget {
100 2     2 0 15 $_[0]->{lastget};
101             }
102              
103             sub lag {
104 2     2 0 14 $_[0]->{lag};
105             }
106              
107             sub age {
108 2     2 0 26 $_[0]->{lastget} - $_[0]->{timestamp};
109             }
110              
111              
112              
113              
114              
115             #####################################################################
116             # Load Methods
117              
118             sub read {
119 3     3 0 4247 my $class = shift;
120              
121             # Check the file to read
122 3         7 my $root = shift;
123 3 50 33     100 unless ( defined _STRING($root) and -d $root ) {
124 0         0 Carp::croak("Directory '$root' does not exist");
125             }
126              
127             # Convert to a usable URI
128 3         333 my $uri = URI::file->new(
129             File::Spec->canonpath(
130             File::Spec->rel2abs($root)
131             )
132             )->canonical;
133              
134             # In a URI a directory must have an explicit trailing slash
135 3         13808 $uri->path( $uri->path . '/' );
136              
137             # Hand off to the URI fetcher
138 3         259 return $class->get( $uri, @_ );
139             }
140              
141             sub get {
142 5     5 0 14 my $class = shift;
143              
144             # Check the URI
145 5         12 my $base = shift;
146 5 50       67 unless ( _INSTANCE($base, 'URI') ) {
147 0         0 Carp::croak("Missing or invalid URI");
148             }
149 5 50       91 unless ( $base->path =~ /\/$/ ) {
150 0         0 Carp::croak("URI must have a trailing slash");
151             }
152              
153             # Find the file within the root path
154 5         213 my %self = (
155             uri => URI->new( $class->filename )->abs($base)->canonical,
156             );
157              
158             # Pull the file and time it
159 5         2467 $self{lastget} = Time::HiRes::time;
160 5         39 $self{string} = LWP::Simple::get($self{uri});
161 5         125046 $self{lag} = Time::HiRes::time - $self{lastget};
162 5 100       32 unless ( defined $self{string} ) {
163 3         40 return $class->new( %self, valid => 0 );
164             }
165              
166             # Parse the file
167 2         26 my $hash = $class->parse( $self{string} );
168 2 50       15 unless ( ref $hash eq 'HASH' ) {
169 0         0 return $class->new( %self, valid => 0 );
170             }
171              
172             # Create the object
173 2         45 return $class->new( %$hash, %self, valid => 1 );
174             }
175              
176              
177              
178              
179              
180             #####################################################################
181             # Populate Elements
182              
183             sub get_master {
184 1     1 0 4 my $self = shift;
185 1 50       5 if ( _INSTANCE($self->master, 'URI') ) {
186             # Load the master
187 1         18 my $master = $self->class->get($self->master);
188 1         5 $self->{master} = $master;
189             }
190 1         8 return $self->master;
191             }
192              
193             sub get_mirror {
194 1     1 0 3 my $self = shift;
195 1         3 my $i = shift;
196 1         5 my $uri = $self->{mirrors}->[$i];
197 1 50       7 unless ( defined $uri ) {
198 0         0 Carp::croak("No mirror with index $i");
199             }
200 1 50       152 if ( _INSTANCE($uri, 'URI') ) {
201 1         13 my $mirror = $self->class->get($uri);
202 1         6 $self->{mirrors}->[$i] = $mirror;
203             }
204 1         8 return $self->{mirrors}->[$i];
205             }
206              
207             1;