File Coverage

blib/lib/Alzabo/Exceptions.pm
Criterion Covered Total %
statement 37 79 46.8
branch 5 32 15.6
condition 0 2 0.0
subroutine 9 16 56.2
pod 0 2 0.0
total 51 131 38.9


line stmt bran cond sub pod time code
1             package Alzabo::Exceptions;
2              
3 12     12   74 use strict;
  12         25  
  12         574  
4 12     12   69 use vars qw($VERSION);
  12         30  
  12         703  
5              
6 12     12   6628 use Alzabo::Utils;
  12         37  
  12         9933  
7              
8              
9             $VERSION = 2.0;
10              
11             my %e;
12              
13             BEGIN
14             {
15 12     12   966 %e = ( 'Alzabo::Exception' =>
16             { description =>
17             'Generic exception within the Alzabo API. Should only be used as a base class.',
18             alias => 'exception',
19             },
20              
21             'Alzabo::Exception::Driver' =>
22             { description => 'An attempt to eval a string failed',
23             fields => [ 'sql', 'bind' ],
24             isa => 'Alzabo::Exception',
25             alias => 'driver_exception',
26             },
27              
28             'Alzabo::Exception::Eval' =>
29             { description => 'An attempt to eval a string failed',
30             isa => 'Alzabo::Exception',
31             alias => 'eval_exception',
32             },
33              
34             'Alzabo::Exception::Logic' =>
35             { description =>
36             'An internal logic error occurred (presumably, Alzabo was asked to do something that cannot be done)',
37             isa => 'Alzabo::Exception',
38             alias => 'logic_exception',
39             },
40              
41             'Alzabo::Exception::NoSuchRow' =>
42             { description => 'An attempt to fetch data from the database for a primary key that did not exist in the specified table',
43             isa => 'Alzabo::Exception',
44             alias => 'no_such_row_exception',
45             },
46              
47             'Alzabo::Exception::Params' =>
48             { description => 'An exception generated when there is an error in the parameters passed in a method of function call',
49             isa => 'Alzabo::Exception',
50             alias => 'params_exception',
51             },
52              
53             'Alzabo::Exception::NotNullable' =>
54             { description => 'An exception generated when there is an attempt is made to set a non-nullable column to NULL',
55             isa => 'Alzabo::Exception::Params',
56             fields => [ 'column_name', 'table_name', 'schema_name' ],
57             alias => 'not_nullable_exception',
58             },
59              
60             'Alzabo::Exception::Panic' =>
61             { description => 'An exception generated when something totally unexpected happens',
62             isa => 'Alzabo::Exception',
63             alias => 'panic_exception',
64             },
65              
66             'Alzabo::Exception::RDBMSRules' =>
67             { description => 'An RDBMS rule check failed',
68             isa => 'Alzabo::Exception',
69             alias => 'rdbms_rules_exception',
70             },
71              
72             'Alzabo::Exception::RDBMSRules::RecreateTable' =>
73             { description =>
74             'An exception generated to indicate the a table needs to be recreated as part of a schema SQL diff',
75             isa => 'Alzabo::Exception',
76             alias => 'recreate_table_exception',
77             },
78              
79             'Alzabo::Exception::ReferentialIntegrity' =>
80             { description =>
81             'An operation was attempted that would violate referential integrity',
82             isa => 'Alzabo::Exception',
83             alias => 'referential_integrity_exception',
84             },
85              
86             'Alzabo::Exception::SQL' =>
87             { description =>
88             'An exception generated when there a logical error in a set of operation on an Alzabo::SQLMaker object',
89             isa => 'Alzabo::Exception',
90             alias => 'sql_exception',
91             },
92              
93             'Alzabo::Exception::Storable' =>
94             { description => 'An attempt to call a function from the Storable module failed',
95             isa => 'Alzabo::Exception',
96             alias => 'storable_exception',
97             },
98              
99             'Alzabo::Exception::System' =>
100             { description => 'An attempt to interact with the system failed',
101             isa => 'Alzabo::Exception',
102             alias => 'system_exception',
103             },
104              
105             'Alzabo::Exception::VirtualMethod' =>
106             { description =>
107             'Indicates that the method called must be subclassed in the appropriate class',
108             isa => 'Alzabo::Exception',
109             alias => 'virtual_method_exception',
110             },
111              
112             );
113             }
114              
115 12     12   13247 use Exception::Class (%e);
  12         167530  
  12         3534  
116              
117             Alzabo::Exception->Trace(1);
118              
119             sub import
120             {
121 213     213   726 my ($class, %args) = @_;
122              
123 213         481 my $caller = caller;
124 213 100       894 if ( $args{abbr} )
125             {
126 131 100       676 foreach my $name ( ref $args{abbr} ? @{ $args{abbr} } : $args{abbr} )
  64         202  
127             {
128 12     12   150897 no strict 'refs';
  12         32  
  12         1584  
129 217 50       284 die "Unknown exception abbreviation '$name'" unless defined &{$name};
  217         849  
130 217         419 *{"${caller}::$name"} = \&{$name};
  217         1664  
  217         1462  
131             }
132             }
133             {
134 12     12   104 no strict 'refs';
  12         26  
  12         2407  
  213         438  
135 213         425 *{"${caller}::isa_alzabo_exception"} = \&isa_alzabo_exception;
  213         1191  
136 213         982 *{"${caller}::rethrow_exception"} = \&rethrow_exception;
  213         5911  
137             }
138             }
139              
140             sub isa_alzabo_exception
141             {
142 0     0 0   my ($err, $name) = @_;
143 0 0         return unless defined $err;
144              
145 0 0         my $class =
    0          
146             ! $name
147             ? 'Alzabo::Exception'
148             : $name =~ /^Alzabo::Exception/
149             ? $name
150             : "Alzabo::Exception::$name";
151              
152             {
153 12     12   69 no strict 'refs';
  12         43  
  12         9602  
  0            
154 0           die "no such exception class $class"
155 0 0         unless defined(${"${class}::VERSION"});
156             }
157              
158 0           return Alzabo::Utils::safe_isa($err, $class);
159             }
160              
161             sub rethrow_exception
162             {
163 0     0 0   my $err = shift;
164              
165 0 0         return unless $err;
166              
167 0 0         if ( Alzabo::Utils::safe_can( $err, 'rethrow' ) )
    0          
168             {
169 0           $err->rethrow;
170             }
171             elsif ( ref $err )
172             {
173 0           die $err;
174             }
175 0           Alzabo::Exception->throw( error => $err );
176             }
177              
178              
179             package Alzabo::Exception;
180              
181             sub format
182             {
183 0     0     my $self = shift;
184              
185 0 0         if (@_)
186             {
187 0 0         $self->{format} = shift eq 'html' ? 'html' : 'text';
188             }
189              
190 0   0       return $self->{format} || 'text';
191             }
192              
193             sub as_string
194             {
195 0     0     my $self = shift;
196              
197 0           my $stringify_function = "as_" . $self->format;
198              
199 0           return $self->$stringify_function();
200             }
201              
202             sub as_text
203             {
204 0     0     return $_[0]->full_message . "\n\n" . $_[0]->trace->as_string;
205             }
206              
207             sub as_html
208             {
209 0     0     my $self = shift;
210              
211 0           my $msg = $self->full_message;
212              
213 0           require HTML::Entities;
214 0           $msg = HTML::Entities::encode_entities($msg);
215 0           $msg =~ s/\n/
/;
216              
217 0           my $html = <<"EOF";
218            
219            

System error

220            
221            
222             error: 
223             $msg
224            
225            
226             code stack: 
227            
228             EOF
229              
230 0           foreach my $frame ( $self->trace->frames )
231             {
232 0           my $filename = HTML::Entities::encode_entities( $frame->filename );
233 0           my $line = $frame->line;
234              
235 0           $html .= "$filename: $line
\n";
236             }
237              
238 0           $html .= <<'EOF';
239            
240            
241            
242              
243            
244             EOF
245              
246 0           return $html;
247             }
248              
249             package Alzabo::Exception::Driver;
250              
251             sub full_message
252             {
253 0     0     my $self = shift;
254              
255 0           my $msg = $self->error;
256 0 0         $msg .= "\nSQL: " . $self->sql if $self->sql;
257              
258 0 0         if ( $self->bind )
259             {
260 0 0         my @bind = map { defined $_ ? $_ : '' } @{ $self->bind };
  0            
  0            
261 0 0         $msg .= "\nBIND: @bind" if @bind;
262             }
263              
264 0           return $msg;
265             }
266              
267             1;
268              
269             =head1 NAME
270              
271             Alzabo::Exceptions - Creates all exception subclasses used in Alzabo.
272              
273             =head1 SYNOPSIS
274              
275             use Alzabo::Exceptions;
276              
277             =head1 DESCRIPTION
278              
279             Using this class creates all the exceptions classes used by Alzabo
280             (via the L|Exception::Class> class).
281              
282             See L|Exception::Class> for more information on
283             how this is done.
284              
285             =head1 EXCEPTION CLASSES
286              
287             =over 4
288              
289             =item * Alzabo::Exception
290              
291             This is the base class for all exceptions generated within Alzabo (all
292             exceptions should return true for C<< $@->isa('Alzabo::Exception') >>
293             except those that are generated via internal Perl errors).
294              
295             =item * Alzabo::Exception::Driver
296              
297             An error occured while accessing a database. See
298             L|Alzabo::Driver> for more details.
299              
300             =item * Alzabo::Exception::Eval
301              
302             An attempt to eval something returned an error.
303              
304             =item * Alzabo::Exception::Logic
305              
306             Alzabo was asked to do something logically impossible, like retrieve
307             rows for a table without a primary key.
308              
309             =item * Alzabo::Exception::NoSuchRow
310              
311             An attempt was made to fetch data from the database with a primary key
312             that does not actually exist in the specified table.
313              
314             =item * Alzabo::Exception::NotNullable
315              
316             An attempt was made to set a non-nullable column to C. The
317             "column_name", "table_name", and "schema_name" fields can be used to
318             identify the exact column.
319              
320             =item * Alzabo::Exception::Panic
321              
322             This exception is thrown when something completely unexpected happens
323             (think Monty Python).
324              
325             =item * Alzabo::Exception::Params
326              
327             This exception is thrown when there is a problem with the parameters
328             passed to a method or function. These problems can include missing
329             parameters, invalid values, etc.
330              
331             =item * Alzabo::Exception::RDBMSRules
332              
333             A rule for the relevant RDBMS was violated (bad schema name, table
334             name, column attribute, etc.)
335              
336             =item * Alzabo::Exception::ReferentialIntegrity
337              
338             An insert/update/delete was attempted that would violate referential
339             integrity constraints.
340              
341             =item * Alzabo::Exception::SQL
342              
343             An error thrown when there is an attempt to generate invalid SQL via
344             the Alzabo::SQLMaker module.
345              
346             =item * Alzabo::Exception::Storable
347              
348             A error when trying to freeze, thaw, or clone an object using
349             Storable.
350              
351             =item * Alzabo::Exception::System
352              
353             Some sort of system call (file read/write, stat, etc.) failed.
354              
355             =item * Alzabo::Exception::VirtualMethod
356              
357             A virtual method was called. This indicates that this method should
358             be subclassed.
359              
360             =back
361              
362             =head1 AUTHOR
363              
364             Dave Rolsky,
365              
366             =cut