X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FEngine.pm;h=b42f8bfcc76ac3d8799950cf0aa2e726523522da;hb=d837e1a7eadff19ff04373ad19d22fa293e19db5;hp=257a8cd3f71c9221ea7bd04fc65c8072249c9bea;hpb=91571b7b15fd05fbcb7014a274dc1f03c34e68be;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Engine.pm b/lib/Catalyst/Engine.pm index 257a8cd..b42f8bf 100644 --- a/lib/Catalyst/Engine.pm +++ b/lib/Catalyst/Engine.pm @@ -20,7 +20,7 @@ require Module::Pluggable::Fast; $Data::Dumper::Terse = 1; __PACKAGE__->mk_classdata('components'); -__PACKAGE__->mk_accessors(qw/request response state/); +__PACKAGE__->mk_accessors(qw/counter request response state/); *comp = \&component; *req = \&request; @@ -30,8 +30,9 @@ __PACKAGE__->mk_accessors(qw/request response state/); *finalize_output = \&finalize_body; # For statistics -our $COUNT = 1; -our $START = time; +our $COUNT = 1; +our $START = time; +our $RECURSION = 1000; =head1 NAME @@ -80,20 +81,31 @@ Regex search for a component. =cut sub component { - my ( $c, $name ) = @_; + my $c = shift; - if ( my $component = $c->components->{$name} ) { - return $component; - } + if (@_) { - else { - for my $component ( keys %{ $c->components } ) { - return $c->components->{$component} if $component =~ /$name/i; + my $name = shift; + + if ( my $component = $c->components->{$name} ) { + return $component; + } + + else { + for my $component ( keys %{ $c->components } ) { + return $c->components->{$component} if $component =~ /$name/i; + } } } + return sort keys %{ $c->components }; } +=item $c->counter + +Returns a hashref containing coderefs and execution counts. +(Needed for deep recursion detection) + =item $c->error =item $c->error($error, ...) @@ -130,12 +142,26 @@ sub execute { $c->state(0); my $callsub = ( caller(1) )[3]; + my $action = ''; + if ( $c->debug ) { + $action = $c->actions->{reverse}->{"$code"}; + $action = "/$action" unless $action =~ /\-\>/; + $c->counter->{"$code"}++; + + if ( $c->counter->{"$code"} > $RECURSION ) { + my $error = qq/Deep recursion detected in "$action"/; + $c->log->error($error); + $c->error($error); + $c->state(0); + return $c->state; + } + + $action = "-> $action" if $callsub =~ /forward$/; + } + eval { if ( $c->debug ) { - my $action = $c->actions->{reverse}->{"$code"}; - $action = "/$action" unless $action =~ /\-\>/; - $action = "-> $action" if $callsub =~ /forward$/; my ( $elapsed, @state ) = $c->benchmark( $code, $class, $c, @{ $c->req->args } ); push @{ $c->{stats} }, [ $action, sprintf( '%fs', $elapsed ) ]; @@ -193,10 +219,6 @@ sub finalize { return $status; } -=item $c->finalize_output - -alias to finalize_body - =item $c->finalize_body Finalize body. @@ -364,7 +386,8 @@ sub handler { my $elapsed; ( $elapsed, $status ) = $class->benchmark($handler); $elapsed = sprintf '%f', $elapsed; - my $av = sprintf '%.3f', 1 / $elapsed; + my $av = sprintf '%.3f', + ( $elapsed == 0 ? '??' : ( 1 / $elapsed ) ); my $t = Text::ASCIITable->new; $t->setCols( 'Action', 'Time' ); $t->setColWidth( 'Action', 64, 1 ); @@ -387,7 +410,7 @@ sub handler { return $status; } -=item $c->prepare($r) +=item $c->prepare($engine) Turns the engine-specific request( Apache, CGI ... ) into a Catalyst context . @@ -398,18 +421,25 @@ sub prepare { my ( $class, $engine ) = @_; my $c = bless { + counter => {}, request => Catalyst::Request->new( { arguments => [], cookies => {}, headers => HTTP::Headers->new, parameters => {}, + secure => 0, snippets => [], uploads => {} } ), response => Catalyst::Response->new( - { cookies => {}, headers => HTTP::Headers->new, status => 200 } + { + body => '', + cookies => {}, + headers => HTTP::Headers->new, + status => 200 + } ), stash => {}, state => 0 @@ -425,10 +455,10 @@ sub prepare { } $c->prepare_request($engine); - $c->prepare_path; + $c->prepare_connection; $c->prepare_headers; $c->prepare_cookies; - $c->prepare_connection; + $c->prepare_path; $c->prepare_action; my $method = $c->req->method || ''; @@ -462,8 +492,9 @@ sub prepare { $t->setCols( 'Key', 'Value' ); $t->setColWidth( 'Key', 37, 1 ); $t->setColWidth( 'Value', 36, 1 ); - for my $key ( keys %{ $c->req->params } ) { - my $value = $c->req->params->{$key} || ''; + for my $key ( sort keys %{ $c->req->params } ) { + my $param = $c->req->params->{$key}; + my $value = defined($param) ? $param : ''; $t->addRow( $key, $value ); } $c->log->debug( 'Parameters are', $t->draw ); @@ -592,6 +623,35 @@ Prepare uploads. sub prepare_uploads { } +=item $c->retrieve_components + +Retrieve Components. + +=cut + +sub retrieve_components { + my $self = shift; + + my $class = ref $self || $self; + eval <<""; + package $class; + import Module::Pluggable::Fast + name => '_components', + search => [ + '$class\::Controller', '$class\::C', + '$class\::Model', '$class\::M', + '$class\::View', '$class\::V' + ], + require => 1; + + if ( my $error = $@ ) { + chomp $error; + die qq/Couldn't load components "$error"/; + } + + return $self->_components; +} + =item $c->run Starts the engine. @@ -669,7 +729,7 @@ sub setup_components { my $t = Text::ASCIITable->new( { hide_HeadRow => 1, hide_HeadLine => 1 } ); $t->setCols('Class'); $t->setColWidth( 'Class', 75, 1 ); - $t->addRow($_) for keys %{ $self->components }; + $t->addRow($_) for sort keys %{ $self->components }; $self->log->debug( 'Loaded components', $t->draw ) if ( @{ $t->{tbl_rows} } && $self->debug ); @@ -691,8 +751,8 @@ Returns a hashref containing all your data. sub stash { my $self = shift; - if ( $_[0] ) { - my $stash = $_[1] ? {@_} : $_[0]; + if (@_) { + my $stash = @_ > 1 ? {@_} : $_[0]; while ( my ( $key, $val ) = each %$stash ) { $self->{stash}->{$key} = $val; }