package Aspect::Pointcut::Cflow; use strict; use warnings; use Carp; use Aspect::AdviceContext; use base 'Aspect::Pointcut'; sub init { my $self = shift; carp 'Cflow must be created with 2 parameters' unless @_ == 2; $self->{runtime_context_key} = shift; $self->{spec} = shift; } sub match_run { my ($self, $sub_name, $runtime_context) = @_; my $caller_info = $self->find_caller; return 0 unless $caller_info; my $advice_context = Aspect::AdviceContext->new( sub_name => $caller_info->{sub_name}, pointcut => $self, params => $caller_info->{params}, ); $runtime_context->{$self->{runtime_context_key}} = $advice_context; return 1; } sub find_caller { my $self = shift; my $level = 2; my $caller_info; while (1) { $caller_info = $self->caller_info($level++); last if !$caller_info || $self->match($self->{spec}, $caller_info->{sub_name}); } return $caller_info; } sub caller_info { my ($self, $level) = @_; package DB; my %call_info; @call_info {qw(calling_package sub_name has_params)} = (CORE::caller($level))[0, 3, 4]; return defined $call_info{calling_package}? {%call_info, params => [$call_info{has_params}? @DB::args: ()]}: 0; } 1;