view Lib/IMPL/Exception.pm @ 134:44977efed303

Significant performance optimizations Fixed recursion problems due converting objects to JSON Added cache support for the templates Added discovery feature for the web methods
author wizard
date Mon, 21 Jun 2010 02:39:53 +0400
parents 3df87ee58bee
children 76515373dac0
line wrap: on
line source

package IMPL::Exception;
use strict;
use overload
    '""' => \&ToString,
    'fallback' => 1;
use Carp qw(longmess shortmess);
use Scalar::Util qw(refaddr);

BEGIN {
	require Error;
}

use base qw(IMPL::Object::Accessor Error);

BEGIN {
    __PACKAGE__->mk_accessors( qw(Message Args CallStack Source) );
}

sub indent {
    my ($str,$level) = @_;
    $level ||= 0;
    $str = '' unless defined $str;
    join ("\n", map( "\t"x$level.$_ , split(/\n/,$str) ) );
}

sub new {
    my $class = shift;
    $class = ref $class || $class;
    
    my $this = $class->Error::new() or die "Failed to create an exception";
    
    $this->callCTOR(@_);
    $this->{-text} = $this->Message;
    
    local $Carp::CarpLevel = 0;
    
    $this->CallStack(longmess);
    $this->Source(shortmess);
    
    return $this;
}

sub CTOR {
    my ($this,$message,@args) = @_;
    $this->Message($message || '');
    die new IMPL::Exception("Fatal erorr: cyclic structure in the exceptions were detected, do not use \$\@ while throwing the exception!") if grep ref $_ ? refaddr($this) == refaddr($_) : 0 , @args;
    $this->Args([map defined $_ ? $_ : 'undef', @args]);
}

sub save {
    my ($this,$ctx) = @_;
    
    $ctx->AddVar(Message => $this->Message) if $this->Message;
    $ctx->AddVar(Args => $this->Args) if @{$this->Args};
    $ctx->AddVar(Source => $this->Source);
    $ctx->AddVar(CallStack => $this->CallStack);
}

sub restore {
    my ($class,$data,$instance) = @_;
    
    my %args = @$data;
    
    if ($instance) {
        $instance->callCTOR($args{Message},@{$args{Args}});
    } else {
        $instance = $class->new($args{Message},@{$args{Args}});
    }
    
    $instance->Source($args{Source});
    $instance->CallStack($args{CallStack});
    
    return $instance;
}

sub ToString {
    my $this = shift;
    
    $this->toString();
}

sub toString {
    my ($this,$notrace) = @_;
    ($this->Message || ref $this) . join("\n",'',map { my $s = $_; local $_; indent("$s",1) } @{$this->Args} ) . ( $notrace ? '' : "\n" . $this->CallStack);
}

package IMPL::InvalidOperationException;
our @ISA = qw(IMPL::Exception);
__PACKAGE__->PassThroughArgs;

package IMPL::InvalidArgumentException;
our @ISA = qw(IMPL::Exception);
__PACKAGE__->PassThroughArgs;

package IMPL::DuplicateException;
our @ISA = qw(IMPL::Exception);
__PACKAGE__->PassThroughArgs;

package IMPL::NotImplementedException;
our @ISA = qw(IMPL::Exception);
__PACKAGE__->PassThroughArgs;

package IMPL::SecurityException;
our @ISA = qw(IMPL::Exception);
__PACKAGE__->PassThroughArgs;

package IMPL::AccessDeniedException;
our @ISA = qw(IMPL::SecurityException);
our %CTOR = ( 'IMPL::SecurityException' => sub { 'Access denied' ,@_ } );

package Exception;
our @ISA = qw(IMPL::Exception);
__PACKAGE__->PassThroughArgs;

package IMPL::DeprecatedException;
our @ISA = qw(IMPL::Exception);
our %CTOR = (
    'IMPL::Exception' => sub { @_ ? @_ : "The method is deprecated" }
);

package IMPL::WrongDataException;
our @ISA = qw(IMPL::Exception);
our %CTOR = (
    'IMPL::Exception' => sub { "The input data is wrong", @_ }
);

package IMPL::IOException;
our @ISA = qw(IMPL::Exception);
__PACKAGE__->PassThroughArgs;

1;