File Coverage

blib/lib/Paranoid/Module.pm
Criterion Covered Total %
statement 53 56 94.6
branch 16 20 80.0
condition n/a
subroutine 10 10 100.0
pod 1 1 100.0
total 80 87 91.9


line stmt bran cond sub pod time code
1             # Paranoid::Module -- Paranoid Module Loading Routines
2             #
3             # $Id: lib/Paranoid/Module.pm, 2.09 2021/12/28 15:46:49 acorliss Exp $
4             #
5             # This software is free software. Similar to Perl, you can redistribute it
6             # and/or modify it under the terms of either:
7             #
8             # a) the GNU General Public License
9             # as published by the
10             # Free Software Foundation ; either version 1
11             # , or any later version
12             # , or
13             # b) the Artistic License 2.0
14             # ,
15             #
16             # subject to the following additional term: No trademark rights to
17             # "Paranoid" have been or are conveyed under any of the above licenses.
18             # However, "Paranoid" may be used fairly to describe this unmodified
19             # software, in good faith, but not as a trademark.
20             #
21             # (c) 2005 - 2020, Arthur Corliss (corliss@digitalmages.com)
22             # (tm) 2008 - 2020, Paranoid Inc. (www.paranoid.com)
23             #
24             #####################################################################
25              
26             #####################################################################
27             #
28             # Environment definitions
29             #
30             #####################################################################
31              
32             package Paranoid::Module;
33              
34 29     29   8430 use 5.008;
  29         151  
35              
36 29     29   157 use strict;
  29         116  
  29         841  
37 29     29   181 use warnings;
  29         59  
  29         1047  
38 29     29   178 use vars qw($VERSION @EXPORT @EXPORT_OK %EXPORT_TAGS);
  29         33  
  29         2009  
39 29     29   202 use base qw(Exporter);
  29         57  
  29         2320  
40 29     29   193 use Paranoid;
  29         44  
  29         1496  
41 29     29   645 use Paranoid::Debug qw(:all);
  29         58  
  29         4847  
42 29     29   8572 use Paranoid::Input;
  29         59  
  29         1772  
43 29     29   195 use Carp;
  29         66  
  29         14553  
44              
45             ($VERSION) = ( q$Revision: 2.09 $ =~ /(\d+(?:\.\d+)+)/sm );
46              
47             @EXPORT = qw(loadModule);
48             @EXPORT_OK = @EXPORT;
49             %EXPORT_TAGS = ( all => [@EXPORT_OK], );
50              
51             #####################################################################
52             #
53             # Module code follows
54             #
55             #####################################################################
56              
57             {
58             my %modules; # List of modules compiled
59             # {modules} => boolean
60             my %imports; # List of modules/tagsets imported from callers
61             # {module*tagset*caller} => boolean
62              
63             sub loadModule {
64              
65             # Purpose: Attempts to load a module via an eval. Caches the
66             # result
67             # Returns: True (1) if the module was successfully loaded,
68             # False (0) if there are any errors
69             # Usage: $rv = loadModule($moduleName);
70              
71 44     44 1 191 my $module = shift;
72 44         135 my @args = @_;
73 44         98 my $rv = 0;
74 44         113 my $caller = scalar caller;
75 44 100       265 my $a = @args ? 'qw(' . ( join ' ', @args ) . ')' : '';
76 44         114 my ( $m, $cm );
77              
78 44 50       158 croak 'Mandatory first argument must be a defined module name'
79             unless defined $module;
80              
81 44         205 pdebug( 'entering w/(%s)(%s)', PDLEVEL1, $module, @args );
82 44         154 pIn();
83              
84             # Check to see if module has been loaded already
85 44 100       163 unless ( exists $modules{$module} ) {
86              
87             # First attempt at loading this module, so
88             # detaint and require
89 43 50       227 if ( detaint( $module, 'filename', $m ) ) {
90 43         106 $module = $m;
91             } else {
92 0         0 Paranoid::ERROR =
93             pdebug( 'failed to detaint module name (%s)',
94             PDLEVEL1, $module );
95 0         0 $modules{$module} = 0;
96             }
97              
98             # Skip if the detainting failed
99 43 50       167 unless ( exists $modules{$module} ) {
100              
101             # Try to load it
102 43 100       3673 $modules{$module} = eval "require $module; 1;" ? 1 : 0;
103             pdebug( 'attempted load of %s: %s',
104 43         315 PDLEVEL2, $module, $modules{$module} );
105              
106             }
107             }
108              
109             # Define the module/tagset/caller
110 44 100       160 if (@args) {
111 42 100       194 $a = '()' if $a eq 'qw()';
112             } else {
113 2         5 $a = '';
114             }
115 44         177 $cm = "$module*$a*$caller";
116              
117             # Check to see if this caller has imported these symbols
118             # before
119 44 100       171 if ( $modules{$module} ) {
120 41 50       118 if ( exists $imports{$cm} ) {
121              
122 0         0 pdebug( 'previous attempt to import to %s',
123             PDLEVEL2, $caller );
124              
125             } else {
126              
127 41         173 pdebug( 'importing symbols into %s', PDLEVEL2, $caller );
128 41         3115 $imports{$cm} = eval << "EOF";
129             {
130             package $caller;
131             import $module $a;
132             1;
133             }
134             EOF
135              
136             }
137              
138 41         262 $rv = $imports{$cm};
139             }
140              
141 44         201 pOut();
142 44         195 pdebug( 'leaving w/rv: %s', PDLEVEL1, $modules{$module} );
143              
144             # Return result
145 44         830 return $modules{$module};
146             }
147             }
148              
149             1;
150              
151             __END__