| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Exception::Class::Base; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 6 |  |  | 6 |  | 64866 | use strict; | 
|  | 6 |  |  |  |  | 20 |  | 
|  | 6 |  |  |  |  | 154 |  | 
| 4 | 6 |  |  | 6 |  | 24 | use warnings; | 
|  | 6 |  |  |  |  | 11 |  | 
|  | 6 |  |  |  |  | 232 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | our $VERSION = '1.45'; | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 6 |  |  | 6 |  | 2534 | use Class::Data::Inheritable 0.02; | 
|  | 6 |  |  |  |  | 1690 |  | 
|  | 6 |  |  |  |  | 155 |  | 
| 9 | 6 |  |  | 6 |  | 2487 | use Devel::StackTrace 2.00; | 
|  | 6 |  |  |  |  | 26987 |  | 
|  | 6 |  |  |  |  | 181 |  | 
| 10 | 6 |  |  | 6 |  | 41 | use Scalar::Util qw( blessed ); | 
|  | 6 |  |  |  |  | 9 |  | 
|  | 6 |  |  |  |  | 277 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 | 6 |  |  | 6 |  | 31 | use base qw(Class::Data::Inheritable); | 
|  | 6 |  |  |  |  | 10 |  | 
|  | 6 |  |  |  |  | 1354 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 0 |  |  |  |  | 0 | BEGIN { | 
| 15 | 6 |  |  | 6 |  | 55 | __PACKAGE__->mk_classdata('Trace'); | 
| 16 | 6 |  |  |  |  | 175 | __PACKAGE__->mk_classdata('UnsafeRefCapture'); | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 6 |  |  |  |  | 132 | __PACKAGE__->mk_classdata('NoContextInfo'); | 
| 19 | 6 |  |  |  |  | 145 | __PACKAGE__->NoContextInfo(0); | 
| 20 |  |  |  |  |  |  |  | 
| 21 | 6 |  |  |  |  | 63 | __PACKAGE__->mk_classdata('RespectOverload'); | 
| 22 | 6 |  |  |  |  | 115 | __PACKAGE__->RespectOverload(0); | 
| 23 |  |  |  |  |  |  |  | 
| 24 | 6 |  |  |  |  | 58 | __PACKAGE__->mk_classdata('MaxArgLength'); | 
| 25 | 6 |  |  |  |  | 124 | __PACKAGE__->MaxArgLength(0); | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | sub NoRefs { | 
| 28 | 1 |  |  | 1 | 0 | 478 | my $self = shift; | 
| 29 | 1 | 50 |  |  |  | 4 | if (@_) { | 
| 30 | 1 |  |  |  |  | 3 | my $val = shift; | 
| 31 | 1 |  |  |  |  | 5 | return $self->UnsafeRefCapture( !$val ); | 
| 32 |  |  |  |  |  |  | } | 
| 33 |  |  |  |  |  |  | else { | 
| 34 | 0 |  |  |  |  | 0 | return $self->UnsafeRefCapture; | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  | } | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 40 |  |  | 40 | 1 | 77 | sub Fields { () } | 
| 39 |  |  |  |  |  |  | } | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | use overload | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | # an exception is always true | 
| 44 | 6 |  |  | 6 |  | 340 | bool => sub {1}, '""' => 'as_string', fallback => 1; | 
|  | 6 |  |  | 7 |  | 10 |  | 
|  | 6 |  |  |  |  | 33 |  | 
|  | 7 |  |  |  |  | 568 |  | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | # Create accessor routines | 
| 47 |  |  |  |  |  |  | BEGIN { | 
| 48 | 6 |  |  | 6 |  | 23 | my @fields = qw( message pid uid euid gid egid time trace ); | 
| 49 |  |  |  |  |  |  |  | 
| 50 | 6 |  |  |  |  | 12 | foreach my $f (@fields) { | 
| 51 | 48 |  |  | 50 |  | 133 | my $sub = sub { my $s = shift; return $s->{$f}; }; | 
|  | 50 |  |  |  |  | 2247 |  | 
|  | 50 |  |  |  |  | 235 |  | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | ## no critic (TestingAndDebugging::ProhibitNoStrict) | 
| 54 | 6 |  |  | 6 |  | 861 | no strict 'refs'; | 
|  | 6 |  |  |  |  | 12 |  | 
|  | 6 |  |  |  |  | 879 |  | 
| 55 | 48 |  |  |  |  | 62 | *{$f} = $sub; | 
|  | 48 |  |  |  |  | 174 |  | 
| 56 |  |  |  |  |  |  | } | 
| 57 | 6 |  |  |  |  | 15 | *error = \&message; | 
| 58 |  |  |  |  |  |  |  | 
| 59 | 6 |  |  |  |  | 20 | my %trace_fields = ( | 
| 60 |  |  |  |  |  |  | package => 'package', | 
| 61 |  |  |  |  |  |  | file    => 'filename', | 
| 62 |  |  |  |  |  |  | line    => 'line', | 
| 63 |  |  |  |  |  |  | ); | 
| 64 |  |  |  |  |  |  |  | 
| 65 | 6 |  |  |  |  | 31 | while ( my ( $f, $m ) = each %trace_fields ) { | 
| 66 |  |  |  |  |  |  | my $sub = sub { | 
| 67 | 4 |  |  | 4 |  | 952 | my $s = shift; | 
| 68 | 4 | 50 |  |  |  | 13 | return $s->{$f} if exists $s->{$f}; | 
| 69 |  |  |  |  |  |  |  | 
| 70 | 4 |  |  |  |  | 13 | my $frame = $s->trace->frame(0); | 
| 71 |  |  |  |  |  |  |  | 
| 72 | 4 | 50 |  |  |  | 485 | return $s->{$f} = $frame ? $frame->$m : undef; | 
| 73 | 18 |  |  |  |  | 42 | }; | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | ## no critic (TestingAndDebugging::ProhibitNoStrict) | 
| 76 | 6 |  |  | 6 |  | 38 | no strict 'refs'; | 
|  | 6 |  |  |  |  | 9 |  | 
|  | 6 |  |  |  |  | 200 |  | 
| 77 | 18 |  |  |  |  | 26 | *{$f} = $sub; | 
|  | 18 |  |  |  |  | 5192 |  | 
| 78 |  |  |  |  |  |  | } | 
| 79 |  |  |  |  |  |  | } | 
| 80 |  |  |  |  |  |  |  | 
| 81 | 0 |  |  | 0 | 0 | 0 | sub Classes { Exception::Class::Classes() } | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | sub throw { | 
| 84 | 39 |  |  | 39 | 1 | 9707 | my $proto = shift; | 
| 85 |  |  |  |  |  |  |  | 
| 86 | 39 | 50 |  |  |  | 94 | $proto->rethrow if ref $proto; | 
| 87 |  |  |  |  |  |  |  | 
| 88 | 39 |  |  |  |  | 113 | die $proto->new(@_); | 
| 89 |  |  |  |  |  |  | } | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | sub rethrow { | 
| 92 | 0 |  |  | 0 | 1 | 0 | my $self = shift; | 
| 93 |  |  |  |  |  |  |  | 
| 94 | 0 |  |  |  |  | 0 | die $self; | 
| 95 |  |  |  |  |  |  | } | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | sub new { | 
| 98 | 39 |  |  | 39 | 1 | 51 | my $proto = shift; | 
| 99 | 39 |  | 33 |  |  | 130 | my $class = ref $proto || $proto; | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 39 |  |  |  |  | 75 | my $self = bless {}, $class; | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 39 |  |  |  |  | 121 | $self->_initialize(@_); | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 39 |  |  |  |  | 170 | return $self; | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | sub _initialize { | 
| 109 | 39 |  |  | 39 |  | 49 | my $self = shift; | 
| 110 | 39 | 100 |  |  |  | 120 | my %p    = @_ == 1 ? ( error => $_[0] ) : @_; | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 39 |  | 100 |  |  | 864 | $self->{message} = $p{message} || $p{error} || q{}; | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 39 | 100 |  |  |  | 82 | $self->{show_trace} = $p{show_trace} if exists $p{show_trace}; | 
| 115 |  |  |  |  |  |  |  | 
| 116 | 39 | 100 |  |  |  | 113 | if ( $self->NoContextInfo ) { | 
| 117 | 1 |  |  |  |  | 8 | $self->{show_trace} = 0; | 
| 118 | 1 |  |  |  |  | 3 | $self->{package}    = $self->{file} = $self->{line} = undef; | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  | else { | 
| 121 |  |  |  |  |  |  | # CORE::time is important to fix an error with some versions of | 
| 122 |  |  |  |  |  |  | # Perl | 
| 123 | 38 |  |  |  |  | 297 | $self->{time} = CORE::time(); | 
| 124 | 38 |  |  |  |  | 89 | $self->{pid}  = $$; | 
| 125 | 38 |  |  |  |  | 231 | $self->{uid}  = $<; | 
| 126 | 38 |  |  |  |  | 224 | $self->{euid} = $>; | 
| 127 | 38 |  |  |  |  | 293 | $self->{gid}  = $(; | 
| 128 | 38 |  |  |  |  | 258 | $self->{egid} = $); | 
| 129 |  |  |  |  |  |  |  | 
| 130 | 38 |  |  |  |  | 115 | my @ignore_class   = (__PACKAGE__); | 
| 131 | 38 |  |  |  |  | 60 | my @ignore_package = 'Exception::Class'; | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 38 | 100 |  |  |  | 105 | if ( my $i = delete $p{ignore_class} ) { | 
| 134 | 1 | 50 |  |  |  | 5 | push @ignore_class, ( ref($i) eq 'ARRAY' ? @$i : $i ); | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 38 | 100 |  |  |  | 66 | if ( my $i = delete $p{ignore_package} ) { | 
| 138 | 2 | 50 |  |  |  | 6 | push @ignore_package, ( ref($i) eq 'ARRAY' ? @$i : $i ); | 
| 139 |  |  |  |  |  |  | } | 
| 140 |  |  |  |  |  |  |  | 
| 141 |  |  |  |  |  |  | $self->{trace} = Devel::StackTrace->new( | 
| 142 |  |  |  |  |  |  | ignore_class       => \@ignore_class, | 
| 143 |  |  |  |  |  |  | ignore_package     => \@ignore_package, | 
| 144 |  |  |  |  |  |  | unsafe_ref_capture => $self->UnsafeRefCapture, | 
| 145 |  |  |  |  |  |  | respect_overload   => $self->RespectOverload, | 
| 146 |  |  |  |  |  |  | max_arg_length     => $self->MaxArgLength, | 
| 147 | 38 | 100 |  |  |  | 158 | map { $p{$_} ? ( $_ => delete $p{$_} ) : () } qw( | 
|  | 114 |  |  |  |  | 1164 |  | 
| 148 |  |  |  |  |  |  | frame_filter | 
| 149 |  |  |  |  |  |  | filter_frames_early | 
| 150 |  |  |  |  |  |  | skip_frames | 
| 151 |  |  |  |  |  |  | ), | 
| 152 |  |  |  |  |  |  | ); | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 39 |  |  |  |  | 11380 | my %fields = map { $_ => 1 } $self->Fields; | 
|  | 9 |  |  |  |  | 22 |  | 
| 156 | 39 |  |  |  |  | 131 | while ( my ( $key, $value ) = each %p ) { | 
| 157 | 39 | 100 |  |  |  | 248 | next if $key =~ /^(?:error|message|show_trace)$/; | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 5 | 50 |  |  |  | 13 | if ( $fields{$key} ) { | 
| 160 | 5 |  |  |  |  | 16 | $self->{$key} = $value; | 
| 161 |  |  |  |  |  |  | } | 
| 162 |  |  |  |  |  |  | else { | 
| 163 | 0 |  |  |  |  | 0 | Exception::Class::Base->throw( | 
| 164 |  |  |  |  |  |  | error => "unknown field $key passed to constructor for class " | 
| 165 |  |  |  |  |  |  | . ref $self ); | 
| 166 |  |  |  |  |  |  | } | 
| 167 |  |  |  |  |  |  | } | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | sub context_hash { | 
| 171 | 1 |  |  | 1 | 1 | 2 | my $self = shift; | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | return { | 
| 174 |  |  |  |  |  |  | time => $self->{time}, | 
| 175 |  |  |  |  |  |  | pid  => $self->{pid}, | 
| 176 |  |  |  |  |  |  | uid  => $self->{uid}, | 
| 177 |  |  |  |  |  |  | euid => $self->{euid}, | 
| 178 |  |  |  |  |  |  | gid  => $self->{gid}, | 
| 179 |  |  |  |  |  |  | egid => $self->{egid}, | 
| 180 | 1 |  |  |  |  | 10 | }; | 
| 181 |  |  |  |  |  |  | } | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | sub field_hash { | 
| 184 | 1 |  |  | 1 | 1 | 3 | my $self = shift; | 
| 185 |  |  |  |  |  |  |  | 
| 186 | 1 |  |  |  |  | 2 | my $hash = {}; | 
| 187 |  |  |  |  |  |  |  | 
| 188 | 1 |  |  |  |  | 30 | for my $field ( $self->Fields ) { | 
| 189 | 2 |  |  |  |  | 34 | $hash->{$field} = $self->$field; | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  |  | 
| 192 | 1 |  |  |  |  | 6 | return $hash; | 
| 193 |  |  |  |  |  |  | } | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | sub description { | 
| 196 | 2 |  |  | 2 | 1 | 314 | return 'Generic exception'; | 
| 197 |  |  |  |  |  |  | } | 
| 198 |  |  |  |  |  |  |  | 
| 199 |  |  |  |  |  |  | sub show_trace { | 
| 200 | 9 |  |  | 9 | 1 | 11 | my $self = shift; | 
| 201 |  |  |  |  |  |  |  | 
| 202 | 9 | 50 |  |  |  | 31 | return 0 unless $self->{trace}; | 
| 203 |  |  |  |  |  |  |  | 
| 204 | 9 | 50 |  |  |  | 3167 | if (@_) { | 
| 205 | 0 |  |  |  |  | 0 | $self->{show_trace} = shift; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  |  | 
| 208 | 9 | 100 |  |  |  | 34 | return exists $self->{show_trace} ? $self->{show_trace} : $self->Trace; | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | sub as_string { | 
| 212 | 9 |  |  | 9 | 1 | 103 | my $self = shift; | 
| 213 |  |  |  |  |  |  |  | 
| 214 | 9 |  |  |  |  | 23 | my $str = $self->full_message; | 
| 215 | 9 | 50 | 33 |  |  | 40 | unless ( defined $str && length $str ) { | 
| 216 | 0 |  |  |  |  | 0 | my $desc = $self->description; | 
| 217 | 0 | 0 | 0 |  |  | 0 | $str = defined $desc | 
| 218 |  |  |  |  |  |  | && length $desc ? "[$desc]" : '[Generic exception]'; | 
| 219 |  |  |  |  |  |  | } | 
| 220 |  |  |  |  |  |  |  | 
| 221 | 9 | 100 |  |  |  | 23 | $str .= "\n\n" . $self->trace->as_string | 
| 222 |  |  |  |  |  |  | if $self->show_trace; | 
| 223 |  |  |  |  |  |  |  | 
| 224 | 9 |  |  |  |  | 633 | return $str; | 
| 225 |  |  |  |  |  |  | } | 
| 226 |  |  |  |  |  |  |  | 
| 227 | 8 |  |  | 8 | 1 | 19 | sub full_message { $_[0]->message } | 
| 228 |  |  |  |  |  |  |  | 
| 229 |  |  |  |  |  |  | # | 
| 230 |  |  |  |  |  |  | # The %seen bit protects against circular inheritance. | 
| 231 |  |  |  |  |  |  | # | 
| 232 |  |  |  |  |  |  | ## no critic (BuiltinFunctions::ProhibitStringyEval, ErrorHandling::RequireCheckingReturnValueOfEval) | 
| 233 |  |  |  |  |  |  | eval <<'EOF' if $] == 5.006; | 
| 234 |  |  |  |  |  |  | sub isa { | 
| 235 |  |  |  |  |  |  | my ( $inheritor, $base ) = @_; | 
| 236 |  |  |  |  |  |  | $inheritor = ref($inheritor) if ref($inheritor); | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | my %seen; | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | no strict 'refs'; | 
| 241 |  |  |  |  |  |  | my @parents = ( $inheritor, @{"$inheritor\::ISA"} ); | 
| 242 |  |  |  |  |  |  | while ( my $class = shift @parents ) { | 
| 243 |  |  |  |  |  |  | return 1 if $class eq $base; | 
| 244 |  |  |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | push @parents, grep { !$seen{$_}++ } @{"$class\::ISA"}; | 
| 246 |  |  |  |  |  |  | } | 
| 247 |  |  |  |  |  |  | return 0; | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  | EOF | 
| 250 |  |  |  |  |  |  |  | 
| 251 |  |  |  |  |  |  | sub caught { | 
| 252 | 3 |  |  | 3 | 0 | 640 | my $class = shift; | 
| 253 |  |  |  |  |  |  |  | 
| 254 | 3 |  |  |  |  | 6 | my $e = $@; | 
| 255 |  |  |  |  |  |  |  | 
| 256 | 3 | 100 | 33 |  |  | 29 | return unless defined $e && blessed($e) && $e->isa($class); | 
|  |  |  | 66 |  |  |  |  | 
| 257 | 2 |  |  |  |  | 7 | return $e; | 
| 258 |  |  |  |  |  |  | } | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | 1; | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | # ABSTRACT: A base class for exception objects | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | __END__ |