File Coverage

blib/lib/Crypt/Random/Source/Factory.pm
Criterion Covered Total %
statement 57 66 86.3
branch 6 14 42.8
condition 2 2 100.0
subroutine 17 18 94.4
pod 3 6 50.0
total 85 106 80.1


line stmt bran cond sub pod time code
1             package Crypt::Random::Source::Factory;
2             # ABSTRACT: Load and instantiate sources of random data
3              
4             our $VERSION = '0.11';
5              
6 2     2   23409 use Moo;
  2         31076  
  2         12  
7 2     2   3456 use Carp qw(croak);
  2         4  
  2         111  
8 2     2   1472 use Module::Find;
  2         2490  
  2         154  
9 2     2   13 use Module::Runtime qw(require_module);
  2         5  
  2         12  
10 2     2   2985 use Types::Standard qw(ClassName Bool ArrayRef Str);
  2         142725  
  2         47  
11 2     2   3761 use namespace::clean;
  2         25554  
  2         9  
12              
13             sub get {
14 4     4 1 38 my ( $self, %args ) = @_;
15              
16 4   100     23 my $type = delete $args{type} || "any";
17              
18 4         12 my $method = "new_$type";
19              
20 4 50       22 $self->can($method) or croak "Don't know how to create a source of type $type";
21              
22 4         22 $self->$method(%args);
23             }
24              
25             sub get_weak {
26 2     2 1 3636 my ( $self, @args ) = @_;
27 2         10 $self->get( @args, type => "weak" );
28             }
29              
30             sub get_strong {
31 1     1 1 343 my ( $self, @args ) = @_;
32 1         5 $self->get( @args, type => "strong" );
33             }
34              
35             has weak_source => (
36             isa => ClassName,
37             is => "rw",
38             lazy => 1,
39             builder => 1,
40             clearer => "clear_weak_source",
41             predicate => "has_weak_source",
42             handles => { new_weak => "new" },
43             );
44              
45             sub _build_weak_source {
46 2     2   5613 my $self = shift;
47 2         6 $self->best_available(@{ $self->weak_sources });
  2         9  
48             }
49              
50             has strong_source => (
51             isa => ClassName,
52             is => "rw",
53             lazy => 1,
54             builder => 1,
55             clearer => "clear_strong_source",
56             predicate => 'has_strong_source',
57             handles => { new_strong => "new" },
58             );
59              
60             sub _build_strong_source {
61 1     1   912 my $self = shift;
62 1         2 $self->best_available(@{ $self->strong_sources });
  1         5  
63             }
64              
65             has any_source => (
66             isa => ClassName,
67             is => "rw",
68             lazy => 1,
69             builder => 1,
70             clearer => "clear_any_source",
71             predicate => 'has_any_source',
72             handles => { new_any => 'new' },
73             );
74              
75             sub _build_any_source {
76 1     1   996 my $self = shift;
77 1 50       25 $self->weak_source || $self->strong_source;
78             }
79              
80             has scan_inc => (
81             is => "ro",
82             isa => Bool,
83             lazy => 1,
84             builder => 1,
85             clearer => 'clear_scan_inc',
86             predicate => 'has_scan_inc',
87             );
88              
89             sub _build_scan_inc {
90 2     2   1246 my $self = shift;
91              
92 2 50       9 if ( exists $ENV{CRYPT_RANDOM_NOT_PLUGGABLE} ) {
93 0         0 return !$ENV{CRYPT_RANDOM_NOT_PLUGGABLE};
94             } else {
95 2         45 return 1;
96             }
97             }
98              
99             has weak_sources => (
100             isa => ArrayRef[Str],
101             is => "rw",
102             lazy => 1,
103             builder => 1,
104             clearer => 'clear_weak_sources',
105             predicate => 'has_weak_sources',
106             );
107              
108             sub _build_weak_sources {
109 2     2   1717 my $self = shift;
110              
111 2 50       27 if ( $self->scan_inc ) {
112 2         61 $self->locate_sources("Weak");
113             } else {
114 0         0 return [qw(
115             Crypt::Random::Source::Weak::devurandom
116             Crypt::Random::Source::Weak::openssl
117             Crypt::Random::Source::Weak::rand
118             )];
119             }
120             }
121              
122             has strong_sources => (
123             isa => ArrayRef[Str],
124             is => "rw",
125             lazy => 1,
126             builder => 1,
127             clearer => 'clear_strong_sources',
128             predicate => 'has_strong_sources',
129             );
130              
131             sub _build_strong_sources {
132 1     1   928 my $self = shift;
133              
134 1 50       26 if ( $self->scan_inc ) {
135 1         13 return $self->locate_sources("Strong");
136             } else {
137 0         0 return [qw(
138             Crypt::Random::Source::Strong::devrandom
139             Crypt::Random::Source::Strong::egd
140             )];
141             }
142             }
143              
144             sub best_available {
145 3     3 0 96 my ( $self, @sources ) = @_;
146              
147 3         6 my @available = grep { local $@; eval { require_module($_); $_->available }; } @sources;
  5         9  
  5         10  
  5         20  
  5         57  
148              
149 3         13 my @sorted = sort { $b->rank <=> $a->rank } @available;
  2         14  
150              
151 3 50       86 wantarray ? @sorted : $sorted[0];
152             }
153              
154             sub first_available {
155 0     0 0 0 my ( $self, @sources ) = @_;
156              
157 0         0 foreach my $class ( @sources ) {
158 0         0 local $@;
159 0 0       0 return $class if eval { require_module($class); $class->available };
  0         0  
  0         0  
160             }
161             }
162              
163             sub locate_sources {
164 3     3 0 7 my ( $self, $category ) = @_;
165 3         23 my @sources = findsubmod "Crypt::Random::Source::$category";
166             # Untaint class names (which are tainted in taint mode because
167             # they came from the disk).
168 3         6579 ($_) = $_ =~ /^(.*)$/ foreach @sources;
169 3         78 return \@sources;
170             }
171              
172             1;
173              
174             =pod
175              
176             =encoding UTF-8
177              
178             =head1 NAME
179              
180             Crypt::Random::Source::Factory - Load and instantiate sources of random data
181              
182             =head1 VERSION
183              
184             version 0.11
185              
186             =head1 SYNOPSIS
187              
188             use Crypt::Random::Source::Factory;
189              
190             my $f = Crypt::Random::Source::Factory->new;
191              
192             my $strong = $f->get_strong;
193              
194             my $weak = $f->get_weak;
195              
196             my $any = $f->get;
197              
198             =head1 DESCRIPTION
199              
200             This class implements a loading and instantiation factory for
201             L objects.
202              
203             If C<$ENV{CRYPT_RANDOM_NOT_PLUGGABLE}> is set then only a preset list of
204             sources will be tried. Otherwise L will be used to locate any
205             installed sources, and use the first available one.
206              
207             =head1 METHODS
208              
209             =head2 get %args
210              
211             Instantiate any random source, passing %args to the constructor.
212              
213             The C argument can be C, C or C.
214              
215             =head2 get_weak %args
216              
217             =head2 get_strong %args
218              
219             Instantiate a new weak or strong random source.
220              
221             =head1 SUPPORT
222              
223             Bugs may be submitted through L
224             (or L).
225              
226             =head1 AUTHOR
227              
228             יובל קוג'מן (Yuval Kogman)
229              
230             =head1 COPYRIGHT AND LICENCE
231              
232             This software is copyright (c) 2008 by Yuval Kogman.
233              
234             This is free software; you can redistribute it and/or modify it under
235             the same terms as the Perl 5 programming language system itself.
236              
237             =cut
238              
239             __END__