From 4e1b93ea24d03b2ec64e0da3366ca40c5a9aa6b9 Mon Sep 17 00:00:00 2001 From: Andrew Yates <ayates@ebi.ac.uk> Date: Tue, 10 Jan 2012 10:52:48 +0000 Subject: [PATCH] Code used to create dynamic proxies --- modules/Bio/EnsEMBL/Utils/Proxy.pm | 192 +++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 modules/Bio/EnsEMBL/Utils/Proxy.pm diff --git a/modules/Bio/EnsEMBL/Utils/Proxy.pm b/modules/Bio/EnsEMBL/Utils/Proxy.pm new file mode 100644 index 0000000000..50936f3664 --- /dev/null +++ b/modules/Bio/EnsEMBL/Utils/Proxy.pm @@ -0,0 +1,192 @@ +=head1 LICENSE + + Copyright (c) 1999-2011 The European Bioinformatics Institute and + Genome Research Limited. All rights reserved. + + This software is distributed under a modified Apache license. + For license details, please see + + http://www.ensembl.org/info/about/code_licence.html + +=head1 CONTACT + + Please email comments or questions to the public Ensembl + developers list at <dev@ensembl.org>. + + Questions may also be sent to the Ensembl help desk at + <helpdesk@ensembl.org>. + +=cut + +=head1 NAME + +Bio::EnsEMBL::Utils::Proxy + +=head1 SYNOPSIS + + #Simple arounds logging proxy + package myproxy; + use base qw/Bio::EnsEMBL::Utils::Proxy/; + sub __resolver { + my ($invoker, $package, $method) = @_; + return sub { + my ($self, @args); + warn "Entering into ${package}::${method}"; + my @capture = $self->$method(@args); + warn "Exiting from ${package}::${method}"; + return @capture; + }; + } + + 1; + +=head1 DESCRIPTION + +This class offers Proxy objects similar to those found in Java's +C<java.lang.reflect.Proxy> object. This class should be overriden and +then implement C<__resolver()>. The C<__resolver()> method returns a +subroutine to the intended action which the proxy object installs into +the calling class' scope. + +All methods internal to the proxy are prefixed with a double underscore +to avoid corruption/intrusion into the normal public and private scope of +most classes. + +=head1 METHODS + +=cut + +package Bio::EnsEMBL::Utils::Proxy; + +use Bio::EnsEMBL::Utils::Exception qw/throw/; + +use vars '$AUTOLOAD'; + +=head2 new + + Arg [1] : The object to proxy + Example : my $newobj = Bio::EnsEMBL::Utils::Proxy->new($myobj); + Description : Provides a new instance of a proxy + Returntype : Bio::EnsEMBL::Utils::Proxy the new instance + Exceptions : None + Caller : public + Status : - + +=cut + +sub new { + my ($class, $proxy) = @_; + my $self = bless({}, ref($class)||$class); + $self->{__proxy} = $proxy; + return $self; +} + +=head2 __proxy + + Example : - + Description : The proxy accessor + Returntype : Any the proxied object + Exceptions : None + Caller : - + Status : - + +=cut + +sub __proxy { + my ($self) = @_; + return $_[0]->{__proxy}; +} + +=head2 isa + + Args : Object type to test + Example : $obj->isa('Bio::EnsEMBL::Utils::Proxy'); + Description : Overriden to provide C<isa()> support for proxies. Will return + true if this object is assignable to the given type or the + proxied object is + Returntype : Boolean; performs same as a normal can + Exceptions : None + Caller : caller + Status : status + +=cut + + +sub isa { + my ($self, $class) = @_; + return 1 if $self->SUPER::isa($class); + return 1 if $self->__proxy()->isa($class); + return 0; +} + +=head2 can + + Args : Method name to test + Example : $obj->can('__proxy'); + Description : Overriden to provide C<can()> support for proxies. Will return + true if this object implements the given method or the + proxied object can + Returntype : Code; performs same as a normal can + Exceptions : None + Caller : caller + Status : status + +=cut + +sub can { + my ($self, $method) = @_; + return 1 if $self->SUPER::can($method); + return 1 if $self->__proxy()->can($method); + return 0; +} + +=head2 DESTROY + + Example : - + Description : Provided because of AutoLoad + Returntype : None + Exceptions : None + Caller : - + Status : - + +=cut + + + +sub DESTROY { + # left blank +} + +=head2 AUTOLOAD + + Example : - + Description : Performs calls to C<__resolver()> and installs the subroutine + into the current package scope. + Returntype : None + Exceptions : Thrown if C<__resolver()> could not return a subroutine + Caller : - + Status : - + +=cut + +sub AUTOLOAD { + my ($self, @args) = @_; + my ($package_name, $method_name) = $AUTOLOAD =~ m/ (.*) :: (.*) /xms; + my $sub = $self->__resolver($package_name, $method_name, @args); + if(! $sub) { + my $type = ref $self ? 'object' : 'class'; + throw qq{Can't locate $type method "$method_name" via package "$package_name". No subroutine was generated}; + } + *$AUTOLOAD = $sub; + goto &$sub; +} + +sub __resolver { + my ($self, $package_name, $method, @args) = @_; + #override to provide the subroutine to install + throw "Unimplemented __resolver() in $package_name. Please implement"; +} + +1; + +__END__ \ No newline at end of file -- GitLab