package Apache::PerlVINC;
use strict;
use Apache::ModuleConfig ();
use Apache::Constants qw(DECLINE_CMD OK DECLINED);
use DynaLoader ();
$Apache::PerlVINC::VERSION = '0.03';
if($ENV{MOD_PERL})
{
no strict;
@ISA = qw(DynaLoader);
__PACKAGE__->bootstrap($VERSION); #command table, etc.
}
sub new { return bless {}, shift }
#------------------------------------------------------------#
#---------------Configuration Directive Methods--------------#
#------------------------------------------------------------#
sub PerlINC ($$$)
{
my($cfg, $parms, $path) = @_;
$cfg->{INC} = $path;
}
sub PerlVersion ($$@)
{
my($cfg, $parms, $name) = @_;
$cfg->{'Files'}->{$name}++;
}
sub handler
{
my $r = shift;
my $cfg = Apache::ModuleConfig->get($r, __PACKAGE__);
if ($r->current_callback() eq "PerlCleanupHandler")
{
map { delete $INC{$_} } keys %{$cfg->{Files}};
return OK;
}
local @INC = @INC;
unshift @INC, @{ $cfg->{'VINC'} };
for (keys %{ $cfg->{'Files'} })
{
delete $INC{$_};
#let mod_perl catch any error thrown here
require $_;
}
return OK;
}
#------------------------------------------------------------#
#----------------Configuration Merging Routines--------------#
#------------------------------------------------------------#
sub DIR_CREATE
{
my $self = shift->new();
$self->{VINC} ||= [];
$self->{Files} ||= {};
return $self;
}
sub DIR_MERGE
{
my ($prt, $kid) = @_;
my %new = (%$prt, %$kid);
$new{INC} = $prt->{INC} if $kid->{INC} eq "";
%{$new{Files}} = (%{$prt->{Files}}, %{$kid->{Files}});
# INC paths get built here
@{$new{VINC}} = ($prt->{INC}, $kid->{INC});
return bless \%new, ;
}
1;
__END__
=head1 NAME
Apache::PerlVINC - Allows versioning of modules among directories or v-hosts.
=head1 SYNOPSIS
#example httpd.conf:
# include the module. this line must be here.
PerlModule Apache::PerlVINC
# set the include path
PerlINC /home/dave/site/files/modules
# make sure VINC reloads the modules
PerlFixupHandler Apache::PerlVINC
# aptionally have VINC unload versioned modules
PerlCleanupHandler Apache::PerlVINC
# reloads Stuff::Things for all requests
PerlVersion Stuff/Things.pm
SetHandler perl-script
PerlHandler Spellcheck
# reload version of this module found in PerlINC line
PerlVersion Spellcheck.pm
PerlModule Apache::PerlVINC
SetHandler perl-script
PerlHandler Spellcheck
PerlFixupHandler Apache::PerlVINC
# only reload for requests in /Spellcheck
PerlINC /home/steve/site/files/modules
PerlVersion Spellcheck.pm # makes PerlVINC load this version
=head1 DESCRIPTION
With this module you can run two copies of a module without having to
worry about which version is being used. Suppose you have two C
or C that want to each use their own version of C.
Durning the FixUp phase, C will tweak C<@INC> and reload
C. Optionally, it will unload that version if you specify
C as a PerlCleanUpHandler.
As you can guess, this module slows things down a little because it unloads and
reloads on a per-request basis. Hence, this module should only be used in a
development environment, not a mission critical one.
=head1 DIRECTIVES
=over 4
=item PerlINC
Takes only one argument: the path to be prepended to C<@INC>. In v0.1, this was
stored internally as an array. This is no longer the case. However, it still works
somewhat as expected in that subsequent calls to C will not overwrite the
previous ones, provided they are not in the same config section (see BUGS). They will
both be prepended to C<@INC>. Note that C<@INC> is not changed for the entire request,
so dont count on that path being in C<@INC> for your scripts.
=item PerlVersion
This directives specifies the files you want reloaded. Depending on where this
directive sits, files will be loaded (and perhaps unloaded). Ie. if this sits in
a C section, the files will only be reloaded on requests to that location.
If this lies in a server section, all requests to the server or v-host will have
these files reloaded.
=back
=head1 BUGS AND LIMITATIONS
Under some setups, C'ing PerlVINC will cause the server to silently
crash on startup. Upgrading C to v/1.04 might fix the problem. As
of this writing, the current version of mod_perl (1.24) does not contain this version
of C. Until the next version is released, you will have to obtain
it from the latest cvs snapshot.
If the C directive is used twice in the same config section, the first call
will be overwritten. Ie.
PerlINC /qwe
PerlINC /poi
PerlINC /zxc
For requests outside of /asdf/, @INC will contain /poi. Inside /asdf/ @INC will
contain /zxc and /poi. This is kinda sucky, I know, and I hope to fix for the next
release.
=head1 AUTHORS
Doug MacEachern
Dave Moore
=head1 COPYRIGHT
This library is free software. You can redistribute it and/or
modify it under the same terms as Perl itself.
=cut