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.12';
5              
6 2     2   14414 use Moo;
  2         18727  
  2         8  
7 2     2   2020 use Carp qw(croak);
  2         4  
  2         93  
8 2     2   786 use Module::Find;
  2         2310  
  2         106  
9 2     2   9 use Module::Runtime qw(require_module);
  2         1  
  2         8  
10 2     2   987 use Types::Standard qw(ClassName Bool ArrayRef Str);
  2         90687  
  2         27  
11 2     2   2195 use namespace::clean;
  2         15429  
  2         6  
12              
13             sub get {
14 4     4 1 25 my ( $self, %args ) = @_;
15              
16 4   100     18 my $type = delete $args{type} || "any";
17              
18 4         7 my $method = "new_$type";
19              
20 4 50       15 $self->can($method) or croak "Don't know how to create a source of type $type";
21              
22 4         14 $self->$method(%args);
23             }
24              
25             sub get_weak {
26 2     2 1 2165 my ( $self, @args ) = @_;
27 2         8 $self->get( @args, type => "weak" );
28             }
29              
30             sub get_strong {
31 1     1 1 219 my ( $self, @args ) = @_;
32 1         3 $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   3578 my $self = shift;
47 2         3 $self->best_available(@{ $self->weak_sources });
  2         7  
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   656 my $self = shift;
62 1         1 $self->best_available(@{ $self->strong_sources });
  1         3  
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   711 my $self = shift;
77 1 50       15 $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   883 my $self = shift;
91              
92 2 50       6 if ( exists $ENV{CRYPT_RANDOM_NOT_PLUGGABLE} ) {
93 0         0 return !$ENV{CRYPT_RANDOM_NOT_PLUGGABLE};
94             } else {
95 2         29 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   1193 my $self = shift;
110              
111 2 50       6 if ( $self->scan_inc ) {
112 2         41 $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   587 my $self = shift;
133              
134 1 50       16 if ( $self->scan_inc ) {
135 1         7 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 61 my ( $self, @sources ) = @_;
146              
147 3         6 my @available = grep { local $@; eval { require_module($_); $_->available }; } @sources;
  5         5  
  5         5  
  5         13  
  5         35  
148              
149 3         8 my @sorted = sort { $b->rank <=> $a->rank } @available;
  2         9  
150              
151 3 50       62 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 5 my ( $self, $category ) = @_;
165 3         11 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         3685 ($_) = $_ =~ /^(.*)$/ foreach @sources;
169 3         58 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.12
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__