/usr/local/CPAN/hub-standard/Hub/Base/Package.pm
package Hub::Base::Package;
use strict;
use Hub qw/:lib/;
our ($AUTOLOAD);
our $VERSION = '4.00043';
our @EXPORT = qw//;
our @EXPORT_OK = qw/modexec/;
use constant RTMOD_NAME => 'module.pm'; # Default runtime module name
use constant RTMOD_INVOKE => 'run'; # Default runtime invokation method
# ------------------------------------------------------------------------------
# modexec - Execute runtime module
# ------------------------------------------------------------------------------
sub modexec {
my $opts = Hub::opts(\@_, {
filename => RTMOD_NAME,
method => RTMOD_INVOKE,
});
$$opts{'method'} = RTMOD_INVOKE unless defined $$opts{'method'};
my $args = shift || [];
my $path = Hub::srcpath($$opts{'filename'});
if ($path) {
my $pkg = mkinst('Package', $path);
return $pkg->call($$opts{'method'}, @$args);
} else {
confess ("Module not found: $$opts{'filename'}");
}#if
}#modexec
# ------------------------------------------------------------------------------
# new - Constructor
# new $module_filename
# This creates a singleton adapter of the perl module
# ------------------------------------------------------------------------------
sub new {
my $self = shift;
my $path = shift or confess "Filename required";
my $classname = ref($self) || $self;
my $filename = Hub::abspath($path)
or confess "Module does not exist: $path";
my $object = Hub::fhandler($filename, $classname);
unless( $object ) {
my $workdir = Hub::getpath($filename);
my $package = $filename;
$package =~ s/[\s\W]/_/g;
$self = {
'filename' => $filename,
'package' => $package,
'workdir' => $workdir,
};
$object = bless $self, $classname;
Hub::fattach($filename, $object);
}#unless
return $object;
}#new
# ------------------------------------------------------------------------------
# call - Call a method in the underlying package
# call $method, [@parameters]
# Note that wrapped methods do not pass the 'defined' test
# ------------------------------------------------------------------------------
sub call {
my $self = shift;
my $classname = ref($self) or croak "Illegal call to instance method";
my $method = shift or croak "Method required";
my $sub = $$self{'package'} . '::' . $method;
no strict 'refs';
Hub::pushwp($$self{'workdir'});
my $result = &$sub(@_);
Hub::popwp();
return $result;
}#call
# ------------------------------------------------------------------------------
# AUTOLOAD - Proxy the call to the underlying package
# ------------------------------------------------------------------------------
sub AUTOLOAD {
my $self = shift;
my $classname = ref($self) or croak "Illegal call to instance method";
my $name = $AUTOLOAD;
if( $name =~ /::(\w+)$/ ) {
return $self->call($1, @_);
} else {
die "Unhandled AUTOLOAD name";
}#if
}#AUTOLOAD
# ------------------------------------------------------------------------------
# DESTROY - Defining this function prevents it from being searched in AUTOLOAD
# ------------------------------------------------------------------------------
sub DESTROY {
}#DESTROY
# ------------------------------------------------------------------------------
# reload - Callback method from L<Hub::Data::FileCache::fattach>
# reload $file_instance
# Called implicty on the first attachment or when the file has been modified
# on disk. Not to be used unless you override L<Hub::Data::FileCache>.
#
# Special patterns:
#
# package PACKAGE; # for dynamically allocating based on full path
#
# import 'foo.pm' as 'FOO'; # for including dynamic packages
# FOO::method();
# ------------------------------------------------------------------------------
sub reload {
my $self = shift;
my $classname = ref($self) or croak "Illegal call to instance method";
my $instance = shift or croak "FileCache file-instance hash required";
#warn "file=$self->{'filename'}\n";
#warn " pkg=$self->{'package'}\n";
my $contents = $$instance{'contents'};
my %imports = ();
Hub::pushwp($$self{'workdir'});
$contents =~ s/\bPACKAGE\b/$self->{'package'}/mg;
$contents =~ s/^\s*IMPORT\s+['"]([^'"]+)['"]\s+AS\s+['"]([A-Z]+)['"];\s*$/
my $fn = $1;
my $alias = $2;
my $pkg = Hub::srcpath("$fn");
$pkg =~ s#[\s\W]#_#g;
$imports{$alias} = $pkg;
"Hub::mkinst('Package', Hub::srcpath('$fn'));\n"/mgei;
foreach my $k (keys %imports) {
$contents =~ s/\b$k\b/$imports{$k}/mg;
}
local $!;
eval $contents;
Hub::popwp();
if( $@ ) {
my $error = $@;
my ($eval_number) = $error =~ s/\(eval (\d+)\)/$$instance{'filename'}/;
die $error;
}#if
}#reload
# ------------------------------------------------------------------------------
1;