File Coverage

blib/lib/Lemonldap/NG/Handler/Initialization/LocalInit.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             ## @file
2             # Base file for Lemonldap::NG handlers
3              
4             ## @class
5             # Base class for Lemonldap::NG handlers.
6             # All methods in handler are class methods: in ModPerl environment, handlers
7             # are always launched without object created.
8             #
9             # The main method is run() who is called by Apache for each requests (using
10             # handler() wrapper).
11             #
12             # The main initialization subroutine is init() who launch localInit() and
13             # globalInit().
14             package Lemonldap::NG::Handler::Initialization::LocalInit;
15              
16 1     1   36466 use Mouse;
  1         34382  
  1         7  
17              
18 1     1   1094 use Lemonldap::NG::Handler::SharedConf; # Needed to get VERSION
  0            
  0            
19             use Lemonldap::NG::Handler::Main::Logger;
20              
21             our $VERSION = '1.3.0';
22              
23             # Mouse attributes
24             ##################
25              
26             # default attributes from constructor
27             has localStorage => ( is => 'rw', isa => 'Maybe[Str]', required => 1 );
28              
29             has refLocalStorage => ( is => 'rw', required => 1 );
30              
31             has localStorageOptions =>
32             ( is => 'rw', isa => 'Maybe[HashRef]', required => 1 );
33              
34             has childInitDone => ( is => 'rw' );
35              
36             # attributes built and returned
37             has [ 'statusPipe', 'statusOut' ] => ( is => 'rw' );
38              
39             BEGIN {
40             if ( exists $ENV{MOD_PERL} ) {
41             if ( $ENV{MOD_PERL_API_VERSION} and $ENV{MOD_PERL_API_VERSION} >= 2 ) {
42             eval 'use constant MP => 2;';
43             }
44             else {
45             eval 'use constant MP => 1;';
46             }
47             }
48             else {
49             eval 'use constant MP => 0;';
50             }
51             if ( MP() == 2 ) {
52             require Apache2::Log;
53             require Apache2::RequestUtil;
54             Apache2::RequestUtil->import();
55             require Apache2::RequestRec;
56             Apache2::RequestRec->import();
57             require Apache2::ServerUtil;
58             Apache2::ServerUtil->import();
59             require Apache2::Connection;
60             Apache2::Connection->import();
61             require Apache2::RequestIO;
62             Apache2::RequestIO->import();
63             require APR::Table;
64             APR::Table->import();
65             require Apache2::URI;
66             Apache2::URI->import();
67             require Apache2::Const;
68             Apache2::Const->import( '-compile', qw(:common :log) );
69             eval '
70             use constant FORBIDDEN => Apache2::Const::FORBIDDEN;
71             use constant REDIRECT => Apache2::Const::REDIRECT;
72             use constant OK => Apache2::Const::OK;
73             use constant DECLINED => Apache2::Const::DECLINED;
74             use constant DONE => Apache2::Const::DONE;
75             use constant SERVER_ERROR => Apache2::Const::SERVER_ERROR;
76             ';
77             }
78             elsif ( MP() == 1 ) {
79             require Apache;
80             require Apache::Log;
81             require Apache::Constants;
82             Apache::Constants->import(':common');
83             Apache::Constants->import(':response');
84             }
85             else { # For Test or CGI
86             eval '
87             use constant FORBIDDEN => 1;
88             use constant REDIRECT => 1;
89             use constant OK => 1;
90             use constant DECLINED => 1;
91             use constant DONE => 1;
92             use constant SERVER_ERROR => 1;
93             ';
94             }
95             }
96              
97             # Mouse methods
98             ###############
99              
100             ## @imethod void localInit(hashRef args)
101             # Call purgeCache() to purge the local cache, launch the status process
102             # (statusProcess()) in wanted and launch childInit().
103             # @param $args reference to the initialization hash
104             sub localInit($$) {
105             my ( $self, $args ) = splice @_;
106             if ( $self->{localStorage} = $args->{localStorage} ) {
107             $self->{localStorageOptions} = $args->{localStorageOptions};
108             $self->{localStorageOptions}->{default_expires_in} ||= 600;
109             $self->purgeCache();
110             }
111             if ( $args->{status} ) {
112             if ( defined $self->{localStorage} ) {
113             $self->statusProcess();
114             }
115             else {
116              
117             # localStorage is mandatory for status module
118             Lemonldap::NG::Handler::Main::Logger->lmLog(
119             "Status module can not be loaded without localStorage parameter",
120             'warn'
121             );
122             }
123             }
124             $self->childInit($args);
125             return (
126             $self->{localStorage}, $self->{refLocalStorage},
127             $self->{localStorageOptions}, $self->{statusPipe},
128             $self->{statusOut}, $self->{childInitDone}
129             );
130             }
131              
132             ## @imethod protected void purgeCache()
133             # Purge the local cache.
134             # Launched at Apache startup.
135             sub purgeCache {
136             my $self = shift;
137             eval "use $self->{localStorage};";
138             die("Unable to load $self->{localStorage}: $@") if ($@);
139              
140             # At each Apache (re)start, we've to clear the cache to avoid living
141             # with old datas
142             eval '$self->{refLocalStorage} = new '
143             . $self->{localStorage}
144             . '($self->{localStorageOptions});';
145             if ( defined $self->{refLocalStorage} ) {
146             $self->{refLocalStorage}->clear();
147             }
148             else {
149             Lemonldap::NG::Handler::Main::Logger->lmLog(
150             "Unable to clear local cache: $@", 'error' );
151             }
152             }
153              
154             # Status daemon creation
155              
156             ## @ifn protected void statusProcess()
157             # Launch the status processus.
158             sub statusProcess {
159             my $self = shift;
160             require IO::Pipe;
161             $self->{statusPipe} = IO::Pipe->new;
162             $self->{statusOut} = IO::Pipe->new;
163             if ( my $pid = fork() ) {
164             $self->{statusPipe}->writer();
165             $self->{statusOut}->reader();
166             $self->{statusPipe}->autoflush(1);
167             }
168             else {
169             require Data::Dumper;
170             $self->{statusPipe}->reader();
171             $self->{statusOut}->writer();
172             my $fdin = $self->{statusPipe}->fileno;
173             my $fdout = $self->{statusOut}->fileno;
174             open STDIN, "<&$fdin";
175             open STDOUT, ">&$fdout";
176             my @tmp = ();
177             push @tmp, "-I$_" foreach (@INC);
178             exec 'perl', '-MLemonldap::NG::Handler::Status',
179             @tmp,
180             '-e',
181             '&Lemonldap::NG::Handler::Status::run('
182             . $self->{localStorage} . ','
183             . Data::Dumper->new( [ $self->{localStorageOptions} ] )->Terse(1)
184             ->Dump . ');';
185             }
186             }
187              
188             ## @imethod protected boolean childInit()
189             # Indicates to Apache that it has to launch:
190             # - initLocalStorage() for each child process (after fork and uid change)
191             # - cleanLocalStorage() after each requests
192             # @return True
193             sub childInit {
194             my ( $self, $args ) = splice @_;
195             return 1 if ( $self->{childInitDone} );
196              
197             # We don't initialise local storage in the "init" subroutine because it can
198             # be used at the starting of Apache and so with the "root" privileges. Local
199             # Storage is also initialized just after Apache's fork and privilege lost.
200              
201             # Local storage is cleaned after giving the content of the page to increase
202             # performances.
203             no strict;
204             if ( MP() == 2 ) {
205             $s = Apache2::ServerUtil->server;
206             $s->push_handlers( PerlChildInitHandler =>
207             sub { return $self->initLocalStorage( $_[1], $_[0] ); } );
208             $s->push_handlers(
209             PerlPostConfigHandler => sub {
210             my ( $c, $l, $t, $s ) = splice @_;
211             $s->add_version_component( 'Lemonldap::NG::Handler/'
212             . $Lemonldap::NG::Handler::VERSION );
213             }
214             ) unless ( $args->{hideSignature} );
215             }
216             elsif ( MP() == 1 ) {
217             Apache->push_handlers(
218             PerlChildInitHandler => sub { return $self->initLocalStorage(@_); }
219             );
220             }
221             $self->{childInitDone}++;
222             1;
223             }
224              
225             ## @imethod protected int initLocalStorage()
226             # Prepare local cache (if not done before by Lemonldap::NG::Common::Conf)
227             # @return Apache2::Const::DECLINED
228             sub initLocalStorage {
229             my ( $self, $r ) = splice @_;
230             if ( $self->{localStorage} and not $self->{refLocalStorage} ) {
231             eval
232             "use $self->{localStorage};\$self->{refLocalStorage} = new $self->{localStorage}(\$self->{localStorageOptions});";
233              
234             Lemonldap::NG::Handler::Main::Logger->lmLog(
235             "Local cache initialization failed: $@", 'error' )
236             unless ( defined $self->{refLocalStorage} );
237             }
238             return DECLINED;
239             }
240              
241             1;