Gateway
view release on metacpan or search on metacpan
News/Gateway.in view on Meta::CPAN
# If our package has been loaded, which it should have been, we can
# derive the name of the directory our modules are in from it.
# Otherwise, we'll do a full @INC search for the module we're looking
# for.
my $name = $INC{"$package.pm"};
if ($name) {
$name =~ s%^(.*)$package\.pm$%$1auto/$package/$module.al%;
undef $name unless (-r $name);
}
unless ($name) { $name = "auto/$package/$module.al" }
# Now comes the fun. We try to load the module. If the routine trying
# to be autoloaded is DESTROY or import, we generate a null one on the
# fly to avoid annoying error messages at shutdown or use time.
#
# We have to handle a few things specially here. First, if the sub that
# we're trying and failing to autoload is mail_error() (which may be
# called by error()), then we have a major problem and need to avoid
# calling more methods. Second, if the first argument to the sub isn't
# a reference (meaning that they're not calling a method), we can't then
# call our error() method since we don't have an object. (This should
# really be fixed by making error() robust in that case....)
my $save = $@;
eval { require $name };
if ($@) {
$@ =~ s/ at .*\n//;
if (substr ($AUTOLOAD, -9) eq '::DESTROY'
|| substr ($AUTOLOAD, -8) eq '::import') {
*$AUTOLOAD = sub {};
} elsif (substr ($AUTOLOAD, -12) eq '::mail_error') {
warn "Autoload of $AUTOLOAD failed: $@\n";
warn "Unable to autoload error methods, aborting\n";
exit $FAILCODE;
} elsif (not ref $_[0]) {
warn "Autoload of $AUTOLOAD failed: $@\n";
warn "Attempted to autoload non-method, aborting\n";
exit $FAILCODE;
} else {
$_[0]->error ("Autoload of $AUTOLOAD failed: $@");
}
}
$@ = $save;
goto &$AUTOLOAD;
}
############################################################################
# Creation and initialization of a new gateway
############################################################################
# This method creates a new gateway object. It takes arguments specifying
# whether we're running interactively (if we are, errors can be dealt with
# by dying; otherwise, we need to send mail), the maintainer (administrative
# contact address) which defaults to the user we're running as if none is
# given, and the envelope sender that should be used for any and all replies
# to articles.
sub new {
my $that = shift;
my $class = ref $that || $that;
my ($interactive, $maintainer, $envelope) = @_;
unless ($maintainer) { $maintainer = (getpwuid ($<))[0] }
unless ($envelope) { $envelope = $maintainer }
my $self = {
confhooks => {},
mesghooks => [],
envelope => $envelope,
interactive => $interactive,
maintainer => $maintainer
};
bless ($self, $class);
}
# Takes a list of modules as arguments and installs all of the callbacks for
# those modules (as determined by the %HOOKS hash defined above). The
# arguments to this constructor can just be a list of modules, or can be an
# intermixed list of modules and module/argument pairs. Arguments must be
# anonymous arrays, and if arguments are present for a module, they're
# passed in to the _init method of the module.
sub modules {
my $self = shift;
my $module;
while (defined ($module = shift)) {
unless (defined $HOOKS{$module}) {
$self->error ("Unknown module $module");
}
my @hook = @{$HOOKS{$module}};
if (ref $_[0]) {
my $method = $module . '_init';
$self->$method (@{+shift});
}
push (@{$$self{mesghooks}}, $module);
for (@hook) { push (@{$$self{confhooks}{$_}}, $module) }
}
}
############################################################################
# Message handling
############################################################################
# Read in the article from a source, returning undef if this fails (either
# because no data is available or because the size limits are exceeded) and
# the number of bytes read if it succeeds. This is mostly just a wrapper
# around the News::Article constructor.
sub read {
my $self = shift;
$$self{article} = News::Article->new (@_);
}
# Apply the given modules, or if none are given, apply all of the ones we
# have pending. Each hook should return undef on success and a string
# indicating the error message on failure; as soon as any hook fails, this
# method aborts and returns a list consisting of the name of the module that
# failed and the error message in an array context or the message prepended
# with the name of the module in a scalar context.
sub apply {
my $self = shift;
my @modules = @_ ? @_ : @{$$self{mesghooks}};
for (@modules) {
my $module = $_ . '_mesg';
my $error = $self->$module ();
( run in 1.913 second using v1.01-cache-2.11-cpan-ceb78f64989 )