| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package CAS::Messaging; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | =head1 NAME | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | CAS::Messaging - Base class for class message & error handling. Not intended | 
| 6 |  |  |  |  |  |  | for external use. | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | use CAS::Constants; | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | Exports the following constants into callers namespace: | 
| 15 |  |  |  |  |  |  | CONTINUE              => 100 | 
| 16 |  |  |  |  |  |  | OK                    => 200 | 
| 17 |  |  |  |  |  |  | CREATED               => 201 | 
| 18 |  |  |  |  |  |  | ACCEPTED              => 202 | 
| 19 |  |  |  |  |  |  | NOT_MODIFIED          => 304 | 
| 20 |  |  |  |  |  |  | BAD_REQUEST           => 400 | 
| 21 |  |  |  |  |  |  | UNAUTHORIZED          => 401 | 
| 22 |  |  |  |  |  |  | AUTH_REQUIRED         => 401 | 
| 23 |  |  |  |  |  |  | FORBIDDEN             => 403 | 
| 24 |  |  |  |  |  |  | NOT_FOUND             => 404 | 
| 25 |  |  |  |  |  |  | METHOD_NOT_ALLOWED    => 405 | 
| 26 |  |  |  |  |  |  | NOT_ACCEPTABLE        => 406 | 
| 27 |  |  |  |  |  |  | REQUEST_TIME_OUT      => 408 | 
| 28 |  |  |  |  |  |  | TIME_EXPIRED          => 408 | 
| 29 |  |  |  |  |  |  | CONFLICT              => 409 | 
| 30 |  |  |  |  |  |  | GONE                  => 410 | 
| 31 |  |  |  |  |  |  | ERROR                 => 500 | 
| 32 |  |  |  |  |  |  | INTERNAL_SERVER_ERROR => 500 | 
| 33 |  |  |  |  |  |  | NOT_IMPLEMENTED       => 501 | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | Definitions of response codes: | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | =over 4 | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | =item B | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | The client may continue with its request. Generally only used inside | 
| 42 |  |  |  |  |  |  | methods where multiple steps may be required. | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | =item B | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | The request has succeeded. Accept for certain special circumstances where | 
| 47 |  |  |  |  |  |  | another code is defined as expected, this is the code that should be set | 
| 48 |  |  |  |  |  |  | when any method completes its task sucessfully (as far as we know). | 
| 49 |  |  |  |  |  |  |  | 
| 50 |  |  |  |  |  |  | =item B | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | The is the code set when a new object was succesfully created. | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | =item B | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | Indicates the request has been accepted for processing, but the processing has | 
| 57 |  |  |  |  |  |  | not been completed. | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | =item B | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | A request was made to save or change something that resulted in no actual | 
| 62 |  |  |  |  |  |  | change, but no system error occured. Such as when setting an attribute to a | 
| 63 |  |  |  |  |  |  | value that is not allowed. | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | =item B | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | The request could not be understood by the server due to malformed syntax or | 
| 68 |  |  |  |  |  |  | missing required arguments. | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | =item B | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | The request requires user authentication. | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | =item B | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | As L. | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | =item B | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | The server understood the request, but is refusing to fulfill it because the | 
| 81 |  |  |  |  |  |  | user or requesting client lacks the required authorization. | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | =item B | 
| 84 |  |  |  |  |  |  |  | 
| 85 |  |  |  |  |  |  | The server understood the request, but the requested resource (such as a user | 
| 86 |  |  |  |  |  |  | or client) was not found. | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | =item B | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | The requested method is not allowed in the current context or by the | 
| 91 |  |  |  |  |  |  | calling object. | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | =item B | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | The client did not produce a request within the time that the server was | 
| 96 |  |  |  |  |  |  | prepared to wait. Or, in the more common context of the user, their log-in | 
| 97 |  |  |  |  |  |  | period has timed out and they need to re-authenticate. | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | =item B | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | As L. | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | =item B | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | The request could not be completed due to a conflict with the current state of | 
| 106 |  |  |  |  |  |  | the resource. | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | =item B | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | The server encountered some condition which prevented it from | 
| 111 |  |  |  |  |  |  | fulfilling the request. Serious internal problems, such as malformed SQL | 
| 112 |  |  |  |  |  |  | statements will also die. This condition is more commonly set when a request | 
| 113 |  |  |  |  |  |  | appeared valid but was impossible to complete, such as a well formed new | 
| 114 |  |  |  |  |  |  | user request, but where the username was already taken. All methods initially | 
| 115 |  |  |  |  |  |  | set the response code to ERROR and then change it when appropriate. | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | =item B | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | As L. | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | =item B | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | The server does not support the functionality required to fulfill the request. | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | =back | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | These values are drawn from Apache's response codes, since this system is | 
| 128 |  |  |  |  |  |  | intended to be generally accessed via an Apache server. While error text | 
| 129 |  |  |  |  |  |  | will be stored in B, the RESPONSE_CODE can be checked to see the | 
| 130 |  |  |  |  |  |  | reason for failure. | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | =cut | 
| 133 |  |  |  |  |  |  |  | 
| 134 | 6 |  |  | 6 |  | 24554 | use strict; | 
|  | 6 |  |  |  |  | 13 |  | 
|  | 6 |  |  |  |  | 278 |  | 
| 135 | 6 |  |  | 6 |  | 37 | use Scalar::Util qw(blessed); | 
|  | 6 |  |  |  |  | 22 |  | 
|  | 6 |  |  |  |  | 424 |  | 
| 136 | 6 |  |  | 6 |  | 35 | use Carp qw(cluck confess croak carp); | 
|  | 6 |  |  |  |  | 27 |  | 
|  | 6 |  |  |  |  | 430 |  | 
| 137 | 6 |  |  | 6 |  | 37 | use base qw(Exporter); | 
|  | 6 |  |  |  |  | 11 |  | 
|  | 6 |  |  |  |  | 1370 |  | 
| 138 |  |  |  |  |  |  |  | 
| 139 |  |  |  |  |  |  | our $VERSION = '0.08'; | 
| 140 |  |  |  |  |  |  | our $AUTOLOAD = ''; | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | our %codes = ( | 
| 143 |  |  |  |  |  |  | CONTINUE              => 100, | 
| 144 |  |  |  |  |  |  | OK                    => 200, | 
| 145 |  |  |  |  |  |  | CREATED               => 201, | 
| 146 |  |  |  |  |  |  | ACCEPTED              => 202, | 
| 147 |  |  |  |  |  |  | NOT_MODIFIED          => 304, | 
| 148 |  |  |  |  |  |  | BAD_REQUEST           => 400, | 
| 149 |  |  |  |  |  |  | UNAUTHORIZED          => 401, | 
| 150 |  |  |  |  |  |  | AUTH_REQUIRED         => 401, | 
| 151 |  |  |  |  |  |  | FORBIDDEN             => 403, | 
| 152 |  |  |  |  |  |  | NOT_FOUND             => 404, | 
| 153 |  |  |  |  |  |  | METHOD_NOT_ALLOWED    => 405, | 
| 154 |  |  |  |  |  |  | NOT_ACCEPTABLE        => 406, | 
| 155 |  |  |  |  |  |  | REQUEST_TIME_OUT      => 408, | 
| 156 |  |  |  |  |  |  | TIME_EXPIRED          => 408, | 
| 157 |  |  |  |  |  |  | CONFLICT              => 409, | 
| 158 |  |  |  |  |  |  | GONE                  => 410, | 
| 159 |  |  |  |  |  |  | ERROR                 => 500, | 
| 160 |  |  |  |  |  |  | INTERNAL_SERVER_ERROR => 500, | 
| 161 |  |  |  |  |  |  | NOT_IMPLEMENTED       => 501, | 
| 162 |  |  |  |  |  |  | ); | 
| 163 | 6 |  |  | 6 |  | 42 | use constant \%codes; | 
|  | 6 |  |  |  |  | 11 |  | 
|  | 6 |  |  |  |  | 497 |  | 
| 164 |  |  |  |  |  |  | use constant { | 
| 165 | 6 |  |  |  |  | 9397 | CONTINUE              => 100, | 
| 166 |  |  |  |  |  |  | OK                    => 200, | 
| 167 |  |  |  |  |  |  | CREATED               => 201, | 
| 168 |  |  |  |  |  |  | ACCEPTED              => 202, | 
| 169 |  |  |  |  |  |  | NOT_MODIFIED          => 304, | 
| 170 |  |  |  |  |  |  | BAD_REQUEST           => 400, | 
| 171 |  |  |  |  |  |  | UNAUTHORIZED          => 401, | 
| 172 |  |  |  |  |  |  | AUTH_REQUIRED         => 401, | 
| 173 |  |  |  |  |  |  | FORBIDDEN             => 403, | 
| 174 |  |  |  |  |  |  | NOT_FOUND             => 404, | 
| 175 |  |  |  |  |  |  | METHOD_NOT_ALLOWED    => 405, | 
| 176 |  |  |  |  |  |  | NOT_ACCEPTABLE        => 406, | 
| 177 |  |  |  |  |  |  | REQUEST_TIME_OUT      => 408, | 
| 178 |  |  |  |  |  |  | TIME_EXPIRED          => 408, | 
| 179 |  |  |  |  |  |  | CONFLICT              => 409, | 
| 180 |  |  |  |  |  |  | GONE                  => 410, | 
| 181 |  |  |  |  |  |  | ERROR                 => 500, | 
| 182 |  |  |  |  |  |  | INTERNAL_SERVER_ERROR => 500, | 
| 183 |  |  |  |  |  |  | NOT_IMPLEMENTED       => 501, | 
| 184 | 6 |  |  | 6 |  | 35 | }; | 
|  | 6 |  |  |  |  | 12 |  | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | our $Errmsg = ''; | 
| 187 |  |  |  |  |  |  | our @EXPORT = (keys %codes,qw($Errmsg)); | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | # we need to be able to get the string by value sometimes | 
| 190 |  |  |  |  |  |  | # it doesn't matter here if an alias gets lost | 
| 191 |  |  |  |  |  |  | our %code_name_by_val = reverse %codes; | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | # set the result information in self | 
| 194 |  |  |  |  |  |  | sub _set_result { | 
| 195 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 196 | 0 | 0 |  |  |  |  | $self->error("Not a method call") unless blessed($self); | 
| 197 | 0 |  | 0 |  |  |  | my $debug = $self->{debug} || 0; | 
| 198 |  |  |  |  |  |  |  | 
| 199 | 0 |  | 0 |  |  |  | my $code = shift || ERROR; # no code == bad ;) | 
| 200 | 0 | 0 |  |  |  |  | $self->error("Unknown result code $code") unless $code_name_by_val{$code}; | 
| 201 | 0 |  |  |  |  |  | $self->{response_code} = $code; | 
| 202 |  |  |  |  |  |  |  | 
| 203 | 0 |  |  |  |  |  | my @call = caller; | 
| 204 | 0 |  |  |  |  |  | my $msg = shift; | 
| 205 | 0 | 0 |  |  |  |  | unless ($msg) { | 
| 206 | 0 |  |  |  |  |  | $msg = 'No message provided by ' . $call[0]; | 
| 207 |  |  |  |  |  |  | } # no message, blame caller | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 0 | 0 |  |  |  |  | if ($debug) { | 
| 210 | 0 |  |  |  |  |  | $msg = "($call[0]:" . "[$call[2]]) $msg"; | 
| 211 |  |  |  |  |  |  | } # if debugging make sure we know where from | 
| 212 |  |  |  |  |  |  |  | 
| 213 | 0 |  |  |  |  |  | push(@{$self->{messages}}, $msg); | 
|  | 0 |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | # If debugging is at 2 or more, we're generating very noisy output as well | 
| 216 | 0 | 0 |  |  |  |  | $self->gripe("_set_result ($code): $msg") if $self->{debug} >= 2; | 
| 217 |  |  |  |  |  |  | } # _set_result | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | sub _clear_result { | 
| 221 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 222 | 0 | 0 |  |  |  |  | $self->error("Not a method call") unless blessed($self); | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | # we set the code to error as any call to _clear_result should be | 
| 225 |  |  |  |  |  |  | # internal, and anything happening before a different result is set that | 
| 226 |  |  |  |  |  |  | # stops processing is almost certainly an error | 
| 227 | 0 |  |  |  |  |  | $self->{response_code} = ERROR; | 
| 228 | 0 |  |  |  |  |  | $self->{messages} = []; | 
| 229 |  |  |  |  |  |  | } # _sclear_result | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  |  | 
| 232 |  |  |  |  |  |  | # Checks to see if the provided code matches the current response_code | 
| 233 |  |  |  |  |  |  | # accept either value or text | 
| 234 |  |  |  |  |  |  | sub response_is { | 
| 235 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 236 | 0 | 0 |  |  |  |  | $self->error("Not a method call") unless blessed($self); | 
| 237 | 0 |  | 0 |  |  |  | my $code = shift || $self->error("No response code specified"); | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 0 | 0 |  |  |  |  | if ($codes{$code}) { $code = $codes{$code} } | 
|  | 0 |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  |  | 
| 241 | 0 | 0 |  |  |  |  | $self->error("Unknown code $code") unless exists $code_name_by_val{$code}; | 
| 242 |  |  |  |  |  |  |  | 
| 243 | 0 | 0 |  |  |  |  | return 1 if $self->{response_code} == $code; | 
| 244 | 0 |  |  |  |  |  | return undef; | 
| 245 |  |  |  |  |  |  | } # response_is | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | # returns the text version of the code, useful mostly in error reporting | 
| 248 |  |  |  |  |  |  | sub response_code { | 
| 249 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 250 | 0 | 0 |  |  |  |  | $self->error("Not a method call") unless blessed($self); | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | # return the key string for the current code | 
| 253 | 0 |  |  |  |  |  | return $code_name_by_val{$self->{response_code}}; | 
| 254 |  |  |  |  |  |  | } # response_code | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | # get the numerical value from the code name | 
| 257 |  |  |  |  |  |  | sub code_value { | 
| 258 | 0 |  |  | 0 | 0 |  | my $self = shift; | 
| 259 | 0 | 0 |  |  |  |  | $self->error("Not a method call") unless blessed($self); | 
| 260 |  |  |  |  |  |  |  | 
| 261 | 0 |  |  |  |  |  | my $name = shift; | 
| 262 | 0 | 0 |  |  |  |  | $self->gripe("Unknown code $name") unless exists $codes{$name}; | 
| 263 | 0 | 0 |  |  |  |  | return $codes{$name} if exists $codes{$name}; | 
| 264 | 0 |  |  |  |  |  | return undef; | 
| 265 |  |  |  |  |  |  | } # response_code | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | =head2 messages | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | Messages return any processing messages. While sometimes useful information | 
| 271 |  |  |  |  |  |  | can be found here for debugging, generally the only reason to call this method | 
| 272 |  |  |  |  |  |  | is to see what happened that caused an error or other invalid response. | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | unless ($user->validate_Password($HR_params)) { | 
| 275 |  |  |  |  |  |  | die "Password not validated: $user->messages"; | 
| 276 |  |  |  |  |  |  | } # unless valid password provided | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | Note that in scalar context messages will return a scalar of all messages | 
| 279 |  |  |  |  |  |  | generated seperated with '; '. In list context it returns a list of the | 
| 280 |  |  |  |  |  |  | messages allowing the caller to format for other display, such as HTML. As | 
| 281 |  |  |  |  |  |  | such, the results of the die above would be very different if written as: | 
| 282 |  |  |  |  |  |  | die "Password not validated: ", $user->messages; | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | When the last method call worked as expected, then the last message in the list | 
| 285 |  |  |  |  |  |  | should be the message generated when the result_code was set. | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | =cut | 
| 288 |  |  |  |  |  |  | sub messages { | 
| 289 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 290 | 0 |  |  |  |  |  | my $class = blessed($self); | 
| 291 | 0 | 0 |  |  |  |  | $self->error("Not a method call") unless $class; | 
| 292 |  |  |  |  |  |  |  | 
| 293 | 0 |  |  |  |  |  | return wantarray ? @{$self->{messages}} | 
|  | 0 |  |  |  |  |  |  | 
| 294 | 0 | 0 |  |  |  |  | : join('; ', $class, @{$self->{messages}}); | 
| 295 |  |  |  |  |  |  | } # messages | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | =head2 errstr | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | Presumes that there was an error, and that the last message generated most | 
| 301 |  |  |  |  |  |  | directly relates to the cause of the error and returns only that message. Be | 
| 302 |  |  |  |  |  |  | warned however that this might always be correct, or enough information. | 
| 303 |  |  |  |  |  |  | Generally the whole message list is prefered. | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | =cut | 
| 306 |  |  |  |  |  |  | sub errstr { | 
| 307 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 308 | 0 | 0 |  |  |  |  | $self->error("Not a method call") unless blessed($self); | 
| 309 |  |  |  |  |  |  |  | 
| 310 | 0 |  |  |  |  |  | return $self->{messages}[-1]; | 
| 311 |  |  |  |  |  |  | } # errstr | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | =head2 error | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | Throw a fatal exeption. Returns a stack trace (confess) if called when | 
| 317 |  |  |  |  |  |  | DEBUG is true. L actually does all the work, error just tells | 
| 318 |  |  |  |  |  |  | gripe to die. | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | =cut | 
| 321 |  |  |  |  |  |  | sub error { | 
| 322 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 323 | 0 | 0 |  |  |  |  | confess("Not a method call") unless blessed($self); | 
| 324 |  |  |  |  |  |  |  | 
| 325 | 0 |  |  |  |  |  | $self->gripe(@_,1); # @_ should only contain the message | 
| 326 |  |  |  |  |  |  | } # error | 
| 327 |  |  |  |  |  |  |  | 
| 328 |  |  |  |  |  |  | =head2 gripe | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | Generate debug sensitive warnings and exceptions. gripe also writes warnings | 
| 331 |  |  |  |  |  |  | to a scratch pad in the calling object so that warning_notes method can | 
| 332 |  |  |  |  |  |  | return all warnings generated. This behavior mirrors that of | 
| 333 |  |  |  |  |  |  | L for objects rather than CGI's. | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | Suggested debug level usage (as level goes up messages from earlier levels | 
| 336 |  |  |  |  |  |  | should continue to be sent): | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | 0:	Production. Perls warnings should _not_ be turned on and no debug | 
| 339 |  |  |  |  |  |  | messages should be generated. | 
| 340 |  |  |  |  |  |  |  | 
| 341 |  |  |  |  |  |  | 1:	Basic development level. Perls warnings are turned on. Basic debug | 
| 342 |  |  |  |  |  |  | messages should be generated. L dies with stack trace (confess) and | 
| 343 |  |  |  |  |  |  | outputs all stored messages. | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  | 2:	Shotgun debugging. Code should now be generating debug messages when | 
| 346 |  |  |  |  |  |  | entering and/or exiting important blocks so that program flow can be | 
| 347 |  |  |  |  |  |  | observed. | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | 3:	Turns on Perls diagnostics. At this level messages should be generated for | 
| 350 |  |  |  |  |  |  | every pass through loops. This would also be the appropriate level to dump | 
| 351 |  |  |  |  |  |  | data structures at critical points. Gripe now includes stack trace with every | 
| 352 |  |  |  |  |  |  | invocation. It is realistic to expect hundreds of lines of output at _least_ at | 
| 353 |  |  |  |  |  |  | this level. This would be the most verbose debug level. | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | 4:	Autodie - gripe will now throw a fatal exception with confess.* | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | * Currently this happens the first time called. However it realy should only | 
| 358 |  |  |  |  |  |  | die the first time a message intended to be sent only at debug levels >= 1. | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | =cut | 
| 361 |  |  |  |  |  |  | sub gripe { | 
| 362 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 363 | 0 |  |  |  |  |  | my $class = blessed($self); | 
| 364 | 0 | 0 |  |  |  |  | croak("Not a method call") unless $class; | 
| 365 | 0 |  | 0 |  |  |  | my $msg = shift || confess("Class $class threw warning without message"); | 
| 366 | 0 |  | 0 |  |  |  | my $die = shift || 0; | 
| 367 |  |  |  |  |  |  |  | 
| 368 | 0 |  |  |  |  |  | my @call = caller; | 
| 369 | 0 | 0 |  |  |  |  | @call = caller(1) if $die; | 
| 370 |  |  |  |  |  |  |  | 
| 371 |  |  |  |  |  |  | # determine debug level, & set to die if told to be extremely verbose | 
| 372 | 0 |  | 0 |  |  |  | my $debug = $self->{debug} || 0; | 
| 373 | 0 | 0 |  |  |  |  | $die = 1 if $debug > 3; | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | # just to be paranoid, we'll unlock tables on fatal error | 
| 376 |  |  |  |  |  |  | # tables left locked can block future operations and would require | 
| 377 |  |  |  |  |  |  | # root to unlock by hand | 
| 378 | 0 | 0 | 0 |  |  |  | if ($die && ref $self->{dbh} && $self->{dbh}->ping) { | 
|  |  |  | 0 |  |  |  |  | 
| 379 | 0 |  |  |  |  |  | $self->{dbh}->do("UNLOCK TABLES"); | 
| 380 |  |  |  |  |  |  | } # if dieing and DBH | 
| 381 |  |  |  |  |  |  |  | 
| 382 | 0 | 0 |  |  |  |  | if ($debug) { | 
| 383 | 0 |  |  |  |  |  | $msg = "($call[0]" . "[$call[2]]) $msg"; | 
| 384 |  |  |  |  |  |  | } # if debugging | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | # to make sure we know what class the object that called us belongs to | 
| 387 | 0 |  |  |  |  |  | $msg = "$class: $msg"; | 
| 388 | 0 | 0 | 0 |  |  |  | if (exists $self->{ERRORLOG} && openhandle($self->{ERRORLOG})) { | 
| 389 | 0 | 0 | 0 |  |  |  | my $logmsg = ($die && $debug) || $debug >= 2 | 
| 390 |  |  |  |  |  |  | ? Carp::longmess($msg) : Carp::shortmess($msg); | 
| 391 | 0 |  |  |  |  |  | my $fh = $self->{ERRORLOG}; | 
| 392 | 0 |  |  |  |  |  | print $fh $logmsg; | 
| 393 |  |  |  |  |  |  | } # if user wants errors loged | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | # if we're dying and debug is on | 
| 396 | 0 | 0 | 0 |  |  |  | if ($die && $debug) { confess("$msg\n" . $self->messages) } | 
|  | 0 | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 397 | 0 |  |  |  |  |  | elsif ($die) { croak($msg) } # or die with just the message | 
| 398 | 0 |  |  |  |  |  | elsif ($debug >= 2) { cluck("$msg\n") } # verbose warn | 
| 399 | 0 |  |  |  |  |  | else { carp("$msg\n") } # just let em know the basics | 
| 400 |  |  |  |  |  |  | } # gripe | 
| 401 |  |  |  |  |  |  |  | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | =head1 AUTHOR | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | Sean P. Quinlan, C<<  >> | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | =head1 TO DO / development notes | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | Gripe should have a way to output to a filehandle (provided when object | 
| 410 |  |  |  |  |  |  | created) so that output can be optionally logged. Should _set_result also | 
| 411 |  |  |  |  |  |  | record each invocation to the log if debugging? | 
| 412 |  |  |  |  |  |  |  | 
| 413 |  |  |  |  |  |  | =head1 BUGS | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | Please report any bugs or feature requests to | 
| 416 |  |  |  |  |  |  | C, or through the web interface at | 
| 417 |  |  |  |  |  |  | L. | 
| 418 |  |  |  |  |  |  | I will be notified, and then you'll automatically be notified of progress on | 
| 419 |  |  |  |  |  |  | your bug as I make changes. | 
| 420 |  |  |  |  |  |  |  | 
| 421 |  |  |  |  |  |  | =head1 HISTORY | 
| 422 |  |  |  |  |  |  |  | 
| 423 |  |  |  |  |  |  | =over 8 | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  | =item 0.01 | 
| 426 |  |  |  |  |  |  |  | 
| 427 |  |  |  |  |  |  | Original version; created by module-starter | 
| 428 |  |  |  |  |  |  |  | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | =back | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  |  | 
| 433 |  |  |  |  |  |  | =head1 SUPPORT | 
| 434 |  |  |  |  |  |  |  | 
| 435 |  |  |  |  |  |  | You can find documentation for this module with the perldoc command. | 
| 436 |  |  |  |  |  |  |  | 
| 437 |  |  |  |  |  |  | perldoc CAS | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | Please join the CAS mailing list and suggest a final release name for | 
| 441 |  |  |  |  |  |  | the package. | 
| 442 |  |  |  |  |  |  | http://mail.grendels-den.org/mailman/listinfo/CAS_grendels-den.org | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | You can also look for information at: | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | =over 4 | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | =item * AnnoCPAN: Annotated CPAN documentation | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | L | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | =item * CPAN Ratings | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | L | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | =item * RT: CPAN's request tracker | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | L | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | =item * Search CPAN | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | L | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | =back | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | =head1 ACKNOWLEDGEMENTS | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | The Bioinformatics Group at Massachusetts General Hospital during my | 
| 469 |  |  |  |  |  |  | tenure there for development assistance and advice, particularly the QA team | 
| 470 |  |  |  |  |  |  | for banging on the project code. | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  |  | 
| 473 |  |  |  |  |  |  | =head1 COPYRIGHT & LICENSE | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | Copyright 2006 Sean P. Quinlan, all rights reserved. | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it | 
| 478 |  |  |  |  |  |  | under the same terms as Perl itself. | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | =cut | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | 1; # End of CAS::Messaging |