Apache-Voodoo

 view release on metacpan or  search on metacpan

lib/Apache/Voodoo/Loader/Dynamic.pm  view on Meta::CPAN

package Apache::Voodoo::Loader::Dynamic;

$VERSION = "3.0200";

use strict;
use warnings;

use base("Apache::Voodoo::Loader");

sub new {
	my $class = shift;

	my $self = {};
	bless $self,$class;

	$self->{'module'} = shift;

	$self->{'bootstrapping'} = 1;
	$self->refresh;
	$self->{'bootstrapping'} = 0;

	$self->{'parents'} = {};
	foreach (eval '@{'.$self->{'module'}.'::ISA}') {
		$self->{'parents'}->{$_} = $self->get_mtime($_);
	}

	return $self;
}

sub init {
	my $self = shift;

	$self->{'config'} = \@_;
	$self->{'object'}->init(@_);
}

sub get_mtime {
	my $self = shift;
	my $file = shift || $self->{'module'};

	$file =~ s/::/\//go;
	$file .= ".pm";

	return 0 unless defined($INC{$file});

	my $mtime = (stat($INC{$file}))[9];

	return $mtime;
}

sub refresh {
	my $self = shift;

	$self->{'object'} = $self->load_module;
	$self->{'mtime'}  = $self->get_mtime;

	# zap our created closures.
	foreach my $method (keys %{$self->{'provides'}}) {
		# a little help from the Cookbook 10.14
		no strict 'refs';
		no warnings 'redefine';
		*$method = undef;
	}
	$self->{'provides'} = {};
}

#
# Override the built in 'can' to allow:
#   a) trigger dynamically reloading the module as needed
#   b) dynamically create closures to link Apache::Voodoo::Handler with the controllers
#
sub can {
	my $self   = shift;
	my $method = shift;
	my $nosub  = shift;

	# find out if this thing has changed
	if ($self->{'mtime'} != $self->get_mtime) {
		$self->refresh;
		$self->{'object'}->init(@{$self->{'config'}});
	}

	if (defined $self->{'provides'}->{$method}) {
		return 1;
	}
	elsif ($self->{'object'}->isa("Apache::Voodoo::Zombie") || $self->{'object'}->can($method)) {
		# Either we have a dead module and we map whatever was requested or
		# we have a live one and has the requested method.

		# cache the existance of this method
		$self->{'provides'}->{$method} = 1;

		# If we used the autoloader to get here, then we want to keep using
		# it. Bypass the creation of the closure.
		unless ($nosub) {
			# create a closeure for this method (a little help from the Cookbook 10.14)
			no strict 'refs';
			no warnings 'redefine';
			*$method = sub { my $self = shift; return $self->_handle($method,@_); };
		}
		return 1;
	}

	return 0;
}



( run in 1.907 second using v1.01-cache-2.11-cpan-39bf76dae61 )