Permalink
Browse files

added exception handling to MojoX::Dispatcher::Routes and Mojo::Loader

  • Loading branch information...
sri
sri committed Jun 23, 2009
1 parent 6ed5bab commit 6b52a2832e3c6339c42927594a8ade2b40eff18e
View
@@ -4,10 +4,14 @@ This file documents the revision history for Perl extension Mojo.
- Rewrote MojoX::Renderer, it is not backward compatible and
templates need to be renamed in the following 3 part format
"index.html.tt"!
+ - Added exception support to MojoX::Dispatcher::Routes, this change
+ is not backward compatible and "dispatch" calls now return
+ exception objects for errors and false for success.
- Added full HTTP 1.1 pipelining support to all Mojo layers.
- Added layout support to MojoX::Renderer.
- Made render call optional.
- Added format support to MojoX::Routes.
+ - Added Mojo::Loader::Exception.
- Added wildcard symbol support to MojoX::Routes and rewrote many
routes internals.
- Added Makefile.PL generator.
View
@@ -10,6 +10,7 @@ use base 'Mojo::Base';
use Carp qw/carp croak/;
use File::Basename;
use File::Spec;
+use Mojo::Loader::Exception;
use constant DEBUG => $ENV{MOJO_LOADER_DEBUG} || 0;
@@ -52,8 +53,7 @@ sub build {
my $instance = $module->new(@_);
push @instances, $instance;
};
- croak qq/Couldn't instantiate module "$module": $@/
- if $@ && $@ ne "SHORTCUT\n";
+ return Mojo::Loader::Exception->new($@) if $@ && $@ ne "SHORTCUT\n";
}
return \@instances;
@@ -71,10 +71,10 @@ sub load {
# Load
eval "require $module";
- croak qq/Couldn't load module "$module": $@/ if $@;
+ return Mojo::Loader::Exception->new($@) if $@;
}
- return $self;
+ return 0;
}
sub load_build {
@@ -84,17 +84,19 @@ sub load_build {
$self = $self->new unless ref $self;
# Load
- $self->load(shift);
+ my $e = $self->load(shift);
+ return $e if $e;
# Build
- my $instances = $self->build(@_);
- return $instances->[0];
+ $e = $self->build(@_);
+ return ref $e eq 'Mojo::Loader::Exception' ? $e : $e->[0];
}
sub reload {
while (my ($key, $file) = each %INC) {
# Modified time
+ next unless $file;
my $mtime = (stat $file)[9];
# Startup time as default
@@ -117,11 +119,13 @@ sub reload {
# Reload
eval { require $key };
- carp "Can't reload '$file': $@" if $@;
+ return Mojo::Loader::Exception->new($@) if $@;
$STATS->{$file} = $mtime;
}
}
+
+ return 0;
}
sub search {
@@ -217,21 +221,27 @@ following new ones.
my $instances = $loader->build;
my $instances = $loader->build(qw/foo bar baz/);
+ my $exception = $loader->build;
+ my $exception = $loader->build(qw/foo bar baz/);
=head2 C<load>
- $loader = $loader->load;
+ my $exception = $loader->load;
=head2 C<load_build>
- my $instance = Mojo::Loader->load_build('MyApp');
- my $instance = $loader->load_build('MyApp');
- my $instance = Mojo::Loader->load_build('MyApp', qw/some args/);
- my $instance = $loader->load_build('MyApp', qw/some args/);
+ my $instance = Mojo::Loader->load_build('MyApp');
+ my $instance = $loader->load_build('MyApp');
+ my $instance = Mojo::Loader->load_build('MyApp', qw/some args/);
+ my $instance = $loader->load_build('MyApp', qw/some args/);
+ my $exception = Mojo::Loader->load_build('MyApp');
+ my $exception = $loader->load_build('MyApp');
+ my $exception = Mojo::Loader->load_build('MyApp', qw/some args/);
+ my $exception = $loader->load_build('MyApp', qw/some args/);
=head2 C<reload>
- Mojo::Loader->reload;
+ my $exception = Mojo::Loader->reload;
=head2 C<search>
@@ -0,0 +1,70 @@
+# Copyright (C) 2008-2009, Sebastian Riedel.
+
+package Mojo::Loader::Exception;
+
+use strict;
+use warnings;
+
+use base 'Mojo::Template::Exception';
+
+use IO::File;
+
+# You killed zombie Flanders!
+# He was a zombie?
+sub new {
+ my $self = shift->SUPER::new();
+
+ # Message
+ my $msg = shift;
+ $self->message($msg);
+
+ if ($msg =~ /at\s+([^\s]+)\s+line\s+(\d+)/) {
+ my $file = $1;
+ my $line = $2;
+
+ # Context
+ if (-r $file) {
+
+ # Slurp
+ my $handle = IO::File->new("< $file");
+ my @lines = <$handle>;
+
+ # Line
+ $self->parse_context(\@lines, $line);
+ }
+ }
+
+ return $self;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Mojo::Loader::Exception - Loader Exception
+
+=head1 SYNOPSIS
+
+ use Mojo::Loader::Exception;
+ my $e = Mojo::Loader::Exception->new;
+
+=head1 DESCRIPTION
+
+L<Mojo::Loader::Exception> is a container for loader exceptions.
+
+=head1 ATTRIBUTES
+
+L<Mojo::Loader::Exception> inherits all methods from
+L<Mojo::Template::Exception>.
+
+=head1 METHODS
+
+L<Mojo::Loader::Exception> inherits all methods from
+L<Mojo::Template::Exception> and implements the following new ones.
+
+=head2 C<new>
+
+ my $e = Mojo::Loader::Exception->new('Something bad happened!');
+
+=cut
View
@@ -39,13 +39,32 @@ sub run {
if ($script) {
my $module =
$self->namespace . '::' . Mojo::ByteStream->new($script)->camelize;
- Mojo::Loader->new->base($self->base)->load_build($module)->run(@args);
+ my $loader = Mojo::Loader->new->base($self->base);
+ my $e = $loader->load_build($module);
+
+ # Exception
+ if (ref $e eq 'Mojo::Loader::Exception') {
+
+ # Module missing
+ die qq/Script "$script" missing, maybe you need to install it?\n/
+ if "$e" =~ /^Can't locate /;
+
+ # Real error
+ die $e;
+ }
+
+ # Run
+ $e->run(@args);
return $self;
}
# Load scripts
- my $instances =
- Mojo::Loader->new($self->namespace)->base($self->base)->load->build;
+ my $loader = Mojo::Loader->new($self->namespace)->base($self->base);
+ my $e = $loader->load;
+ die $e if $e;
+ $e = $loader->build;
+ die $e if ref $e eq 'Mojo::Loader::Exception';
+ my $instances = $e;
# Print overview
print $self->message;
View
@@ -15,7 +15,11 @@ use constant RELOAD => $ENV{MOJO_RELOAD} || 0;
__PACKAGE__->attr(
app => (
chained => 1,
- default => sub { Mojo::Loader->load_build(shift->app_class) }
+ default => sub {
+ my $e = Mojo::Loader->load_build(shift->app_class);
+ die $e if ref $e eq 'Mojo::Loader::Exception';
+ return $e;
+ }
)
);
__PACKAGE__->attr(
@@ -33,7 +37,8 @@ __PACKAGE__->attr(
# Reload
if (RELOAD) {
- Mojo::Loader->reload;
+ my $e = Mojo::Loader->reload;
+ warn $e if $e;
delete $self->{app};
}
View
@@ -303,29 +303,7 @@ sub _error {
my $line = $1;
my @lines = split /\n/, $self->template;
- # Context
- $te->line([$line, $lines[$line - 1]]);
-
- # -2
- my $previous_line = $line - 3;
- my $code = $previous_line >= 0 ? $lines[$previous_line] : undef;
- push @{$te->lines_before}, [$line - 2, $code] if $code;
-
- # -1
- $previous_line = $line - 2;
- $code = $previous_line >= 0 ? $lines[$previous_line] : undef;
- push @{$te->lines_before}, [$line - 1, $code] if $code;
-
- # +1
- my $next_line = $line;
- $code = $next_line >= 0 ? $lines[$next_line] : undef;
- push @{$te->lines_after}, [$line + 1, $code] if $code;
-
- # +2
- $next_line = $line + 1;
- $code = $next_line >= 0 ? $lines[$next_line] : undef;
- push @{$te->lines_after}, [$line + 2, $code] if $code;
-
+ $te->parse_context(\@lines, $line);
}
return $te;
@@ -14,6 +14,49 @@ __PACKAGE__->attr('message' => (chained => 1));
# Attempted murder? Now honestly, what is that?
# Do they give a Nobel Prize for attempted chemistry?
+sub parse_context {
+ my ($self, $lines, $line) = @_;
+
+ # Context
+ my $code = $lines->[$line - 1];
+ chomp $code;
+ $self->line([$line, $code]);
+
+ # -2
+ my $previous_line = $line - 3;
+ $code = $previous_line >= 0 ? $lines->[$previous_line] : undef;
+ if (defined $code) {
+ chomp $code;
+ push @{$self->lines_before}, [$line - 2, $code];
+ }
+
+ # -1
+ $previous_line = $line - 2;
+ $code = $previous_line >= 0 ? $lines->[$previous_line] : undef;
+ if (defined $code) {
+ chomp $code;
+ push @{$self->lines_before}, [$line - 1, $code];
+ }
+
+ # +1
+ my $next_line = $line;
+ $code = $next_line >= 0 ? $lines->[$next_line] : undef;
+ if (defined $code) {
+ chomp $code;
+ push @{$self->lines_after}, [$line + 1, $code];
+ }
+
+ # +2
+ $next_line = $line + 1;
+ $code = $next_line >= 0 ? $lines->[$next_line] : undef;
+ if (defined $code) {
+ chomp $code;
+ push @{$self->lines_after}, [$line + 2, $code];
+ }
+
+ return $self;
+}
+
sub to_string {
my $self = shift;
@@ -38,8 +81,11 @@ sub to_string {
$string .= $line->[0] . ': ' . $line->[1] . "\n";
}
+ # Delim
+ $string .= "$delim\n" if length $string;
+
# Message
- $string .= ("$delim\n" . $self->message) if $self->message;
+ $string .= $self->message if $self->message;
return $string;
}
@@ -54,40 +100,46 @@ Mojo::Template::Exception - Template Exception
=head1 SYNOPSIS
use Mojo::Template::Exception;
- my $te = Mojo::Template::Exception->new;
+ my $e = Mojo::Template::Exception->new;
=head1 DESCRIPTION
+L<Mojo::Template::Exception> is a container for template exceptions.
+
=head1 ATTRIBUTES
=head2 C<line>
- my $line = $te->line;
- $te = $te->line([3, 'foo']);
+ my $line = $e->line;
+ $e = $e->line([3, 'foo']);
=head2 C<lines_after>
- my $lines = $te->lines_after;
- $te = $te->lines_after([[1, 'bar'], [2, 'baz']]);
+ my $lines = $e->lines_after;
+ $e = $e->lines_after([[1, 'bar'], [2, 'baz']]);
=head2 C<lines_before>
- my $lines = $te->lines_before;
- $te = $te->lines_before([[4, 'bar'], [5, 'baz']]);
+ my $lines = $e->lines_before;
+ $e = $e->lines_before([[4, 'bar'], [5, 'baz']]);
=head2 C<message>
- my $message = $te->message;
- $te = $te->message('oops!');
+ my $message = $e->message;
+ $e = $e->message('oops!');
=head1 METHODS
L<Mojo::Template::Exception> inherits all methods from L<Mojo::Base> and
implements the following new ones.
+=head2 C<parse_context>
+
+ $e = $e->parse_context($lines, $line);
+
=head2 C<to_string>
- my $string = $te->to_string;
- my $string = "$te";
+ my $string = $e->to_string;
+ my $string = "$e";
=cut
Oops, something went wrong.

0 comments on commit 6b52a28

Please sign in to comment.