The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#############################################################################
#
# Override certain RPC::XML::Client methods to better fit in
#
# Author:  Chris Weyl (cpan:RSRCHBOY), <cweyl@alumni.drew.edu>
# Company: No company, personal work
# Created: 01/27/2009 07:08:51 PM PST
#
# Copyright (c) 2009 Chris Weyl <cweyl@alumni.drew.edu>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
#############################################################################

package Fedora::Bugzilla::XMLRPC;

use English qw{ -no_match_vars };  # Avoids regex performance penalty

use Moose;

extends 'RPC::XML::Client', 'Moose::Object';

# debugging
#use Smart::Comments '###', '####';

our $VERSION = '0.13';

has login_cb => (is => 'ro', isa => 'CodeRef', required => 1);

sub new { 
    my $class = shift; 
    
    # call XML::RPC's constructor 
    my $obj = $class->SUPER::new(@_); 
    $obj = $class->meta->new_object( 
        # pass in the constructed object using the special key __INSTANCE__ 
        __INSTANCE__ => $obj,
        login_cb     => pop @_,
    );
    $obj->BUILDALL;
    return $obj;
}

around fault_handler => sub {
    my $next = shift @_;
    my $self = shift @_;
    
    if (ref $_[0] eq 'CODE') {

        # we're passed a code ref, so set our new handler
        my $new_handler = shift @_;
        return $next->($self, 
            sub { 

                # login and retry if we're a login failure
                my $fault = $_[0]->{faultString}->value;
                ### fault: "$fault"

                do { $self->login_cb->(); die 'RETRY' } 
                    if "$fault" eq 'Login Required'; 
                
                # otherwise just call the real handler
                return $new_handler->(@_);
            }
        );
    }

    # otherwise just call our handler
    return $next->($self);
};

override send_request => sub {
    my $self = shift @_;

    # let's try it...
    my $ret;
    eval { $ret = super };

    ### $EVAL_ERROR
    return $ret unless $EVAL_ERROR;

    # check to see if it's a 'Login Required' fault
    # if it is, we've already handled the login in the fault handler
    do { return super }
        if $EVAL_ERROR =~ /^RETRY/;

    return $ret;
};

__PACKAGE__->meta->make_immutable(inline_constructor => 0);

1;

__END__

=head1 NAME

Fedora::Bugzilla::XMLRPC - Subclass RPC::XML::Client to catch login faults

=head1 SYNOPSIS

	use <Module::Name>;
	# Brief but working code example(s) here showing the most common usage(s)

	# This section will be as far as many users bother reading
	# so make it as educational and exemplary as possible.


=head1 DESCRIPTION

A subclass of L<RPC::XML::Client>, overriding a number send_request() and
fault_handler() to handle logins when they need to happen.


=head1 SUBROUTINES/METHODS

=over

=item B<fault_handler>

=item B<send_request>

=back

=head1 DIAGNOSTICS

See L<RPC::XML::Client>.  We catch 'Login Required' faults, but everything
else remains the same.

=head1 SEE ALSO

L<RPC::XML::Client>.

=head1 BUGS AND LIMITATIONS

See L<Fedora::Bugzilla>.

Patches are welcome.

=head1 AUTHOR

Chris Weyl  <cweyl@alumni.drew.edu>


=head1 LICENSE AND COPYRIGHT

Copyright (c) 2009 Chris Weyl <cweyl@alumni.drew.edu>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the 

    Free Software Foundation, Inc.
    59 Temple Place, Suite 330
    Boston, MA  02111-1307  USA

=cut