File Coverage

blib/lib/Lemonldap/NG/Handler/SharedConf.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             ## @file
2             # Main handler.
3              
4             ## @class
5             # Main handler.
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 initialization process is splitted in two parts :
13             # - init() is launched as Apache startup
14             # - globalInit() is launched at each first request received by an Apache child
15             # and each time a new configuration is detected
16             package Lemonldap::NG::Handler::SharedConf;
17              
18             #use strict;
19              
20 5     5   2564 use Lemonldap::NG::Handler::Main qw(:all);
  0            
  0            
21             use Lemonldap::NG::Handler::Initialization::GlobalInit;
22              
23             #use Lemonldap::NG::Handler::Vhost;
24             use Lemonldap::NG::Common::Conf; #link protected lmConf
25             use Lemonldap::NG::Common::Conf::Constants; #inherits
26             use Cache::Cache qw($EXPIRES_NEVER);
27             use Lemonldap::NG::Handler::Main::Logger;
28              
29             use Mouse;
30              
31             extends qw(Lemonldap::NG::Handler::Main); # Lemonldap::NG::Handler::Vhost
32              
33             #use base qw(Lemonldap::NG::Handler::Vhost Lemonldap::NG::Handler::Main);
34              
35             #parameter reloadTime Time in second between 2 configuration check (600)
36              
37             our $VERSION = '1.4.0';
38             our $cfgNum = 0;
39             our $lastReload = 0;
40             our $reloadTime;
41             our $lmConf;
42             our $localConfig;
43              
44             BEGIN {
45             if ( MP() == 2 ) {
46             eval {
47             require threads::shared;
48             Apache2::RequestUtil->import();
49             threads::shared::share($cfgNum);
50             threads::shared::share($lastReload);
51             threads::shared::share($reloadTime);
52             threads::shared::share($lmConf);
53             threads::shared::share($localConfig);
54             };
55             }
56             *EXPORT_TAGS = *Lemonldap::NG::Handler::Main::EXPORT_TAGS;
57             *EXPORT_OK = *Lemonldap::NG::Handler::Main::EXPORT_OK;
58             push(
59             @{ $EXPORT_TAGS{$_} },
60             qw($cfgNum $lastReload $reloadTime $lmConf $localConfig)
61             ) foreach (qw(variables localStorage));
62             push @EXPORT_OK, qw($cfgNum $lastReload $reloadTime $lmConf $localConfig);
63             }
64              
65             # INIT PROCESS
66              
67             ## @imethod void init(hashRef args)
68             # Constructor.
69             # init is overloaded to call only localInit. globalInit is called later.
70             # @param $args hash containing parameters
71             sub init($$) {
72             my ( $class, $args ) = splice @_;
73              
74             # TODO reloadTime in defaultValuesInit ?
75             $reloadTime = $args->{reloadTime} || 600;
76             $class->localInit($args);
77             }
78              
79             ## @imethod protected void defaultValuesInit(hashRef args)
80             # Set default values for non-customized variables
81             # @param $args hash containing parameters
82             # @return boolean
83             sub defaultValuesInit {
84             my ( $class, $args ) = splice @_;
85              
86             # Local configuration overrides global configuration
87             my %h = ( %$args, %$localConfig );
88              
89             #return $class->SUPER::defaultValuesInit( \%h );
90              
91             my $globalinit = Lemonldap::NG::Handler::Initialization::GlobalInit->new(
92             customFunctions => $tsv->{customFunctions},
93             useSafeJail => $tsv->{useSafeJail},
94             );
95              
96             (
97             @$tsv{
98             qw( cookieName securedCookie whatToTrace
99             https port customFunctions
100             timeoutActivity useRedirectOnError useRedirectOnForbidden
101             useSafeJail key maintenance )
102             },
103             @$ntsv{
104             qw( cda httpOnly cookieExpiration
105             cipher
106             )
107             }
108             )
109             = $globalinit->defaultValuesInit(
110             @$tsv{
111             qw( cookieName securedCookie whatToTrace
112             https port customFunctions
113             timeoutActivity useRedirectOnError useRedirectOnForbidden
114             useSafeJail key maintenance )
115             },
116             @$ntsv{
117             qw( cda httpOnly cookieExpiration
118             cipher )
119             },
120             \%h
121             );
122              
123             }
124              
125             ## @imethod void localInit(hashRef args)
126             # Load parameters and build the Lemonldap::NG::Common::Conf object.
127             # @return boolean
128             sub localInit {
129             my ( $class, $args ) = splice @_;
130             die(
131             "$class : unable to build configuration : $Lemonldap::NG::Common::Conf::msg"
132             )
133             unless ( $lmConf =
134             Lemonldap::NG::Common::Conf->new( $args->{configStorage} ) );
135              
136             # Get local configuration parameters
137             my $localconf = $lmConf->getLocalConf(HANDLERSECTION);
138             if ($localconf) {
139             $args->{$_} ||= $localconf->{$_} foreach ( keys %$localconf );
140             }
141              
142             # Store in localConfig global variable
143             $localConfig = $args;
144              
145             # localStorage can be declared in configStorage or at the root or both
146             foreach (qw(localStorage localStorageOptions)) {
147             $args->{$_} ||= $args->{configStorage}->{$_} || $lmConf->{$_};
148             $args->{configStorage}->{$_} ||= $args->{$_};
149             }
150              
151             $class->defaultValuesInit($args);
152             $class->SUPER::localInit($args);
153             }
154              
155             # MAIN
156              
157             ## @rmethod int run(Apache2::RequestRec r)
158             # Check configuration and launch Lemonldap::NG::Handler::Main::run().
159             # Each $reloadTime, the Apache child verify if its configuration is the same
160             # as the configuration stored in the local storage.
161             # @param $r Apache2::RequestRec object
162             # @return Apache constant
163             sub run($$) {
164             my ( $class, $r ) = splice @_;
165             if ( time() - $lastReload > $reloadTime ) {
166             die("$class: No configuration found")
167             unless ( $class->testConf(1) == OK );
168             }
169             return $class->SUPER::run($r);
170             }
171              
172             # CONFIGURATION UPDATE
173              
174             ## @rmethod protected int testConf(boolean local)
175             # Test if configuration has changed and launch setConf() if needed.
176             # If the optional boolean $local is true, remote configuration is not tested:
177             # only local cached configuration is tested if available. $local is given to
178             # Lemonldap::NG::Common::getConf()
179             # @param $local boolean
180             # @return Apache constant
181             sub testConf {
182             my ( $class, $local ) = splice @_;
183             my $conf = $lmConf->getConf( { local => $local } );
184             unless ( ref($conf) ) {
185             Lemonldap::NG::Handler::Main::Logger->lmLog(
186             "$class: Unable to load configuration: $Lemonldap::NG::Common::Conf::msg",
187             'error'
188             );
189             return $cfgNum ? OK : SERVER_ERROR;
190             }
191             if ( !$cfgNum or $cfgNum != $conf->{cfgNum} ) {
192             Lemonldap::NG::Handler::Main::Logger->lmLog(
193             "$class: get configuration $conf->{cfgNum} ($Lemonldap::NG::Common::Conf::msg)",
194             'debug'
195             );
196             $lastReload = time();
197             return $class->setConf($conf);
198             }
199             Lemonldap::NG::Handler::Main::Logger->lmLog(
200             "$class: configuration is up to date", 'debug' );
201             OK;
202             }
203              
204             ## @rmethod protected int setConf(hashRef conf)
205             # Launch globalInit().
206             # Local parameters have best precedence on configuration parameters.
207             # @return Apache constant
208             sub setConf {
209             my ( $class, $conf ) = splice @_;
210              
211             # Local configuration overrides global configuration
212             $cfgNum = $conf->{cfgNum};
213             $conf->{$_} = $localConfig->{$_} foreach ( keys %$localConfig );
214             $class->globalInit($conf);
215             OK;
216             }
217              
218             # RELOAD SYSTEM
219              
220             *reload = *refresh;
221              
222             ## @rmethod int refresh(Apache::RequestRec r)
223             # Launch testConf() with $local=0, so remote configuration is tested.
224             # Then build a simple HTTP response that just returns "200 OK" or
225             # "500 Server Error".
226             # @param $r current request
227             # @return Apache constant (OK or SERVER_ERROR)
228             sub refresh($$) {
229             my ( $class, $r ) = splice @_;
230             Lemonldap::NG::Handler::Main::Logger->lmLog(
231             "$class: request for configuration reload", 'notice' );
232             $r->handler("perl-script");
233             if ( $class->testConf(0) == OK ) {
234             if ( MP() == 2 ) {
235             $r->push_handlers( 'PerlResponseHandler' =>
236             sub { my $r = shift; $r->content_type('text/plain'); OK } );
237             }
238             elsif ( MP() == 1 ) {
239             $r->push_handlers(
240             'PerlHandler' => sub { my $r = shift; $r->send_http_header; OK }
241             );
242             }
243             else {
244             return 1;
245             }
246             }
247             else {
248             if ( MP() == 2 ) {
249             $r->push_handlers( 'PerlResponseHandler' => sub { SERVER_ERROR } );
250             }
251             elsif ( MP() == 1 ) {
252             $r->push_handlers( 'PerlHandler' => sub { SERVER_ERROR } );
253             }
254             else {
255             return 0;
256             }
257             }
258             return OK;
259             }
260              
261             1;
262             __END__