/[cvs]/nfo/perl/libs/Data/Storage/Handler/Abstract.pm
ViewVC logotype

Contents of /nfo/perl/libs/Data/Storage/Handler/Abstract.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (show annotations)
Fri Jun 6 03:40:57 2003 UTC (21 years, 1 month ago) by joko
Branch: MAIN
Changes since 1.17: +7 -1 lines
disabled autovivifying of arguments as attributes

1 ## ------------------------------------------------------------------------
2 ## $Id: Abstract.pm,v 1.17 2003/05/13 07:58:49 joko Exp $
3 ## ------------------------------------------------------------------------
4 ## $Log: Abstract.pm,v $
5 ## Revision 1.17 2003/05/13 07:58:49 joko
6 ## fix: die if methodname is empty
7 ## fixes to log-string
8 ##
9 ## Revision 1.16 2003/04/18 16:07:53 joko
10 ## just use logger if instantiation successed
11 ##
12 ## Revision 1.15 2003/02/20 20:19:13 joko
13 ## tried to get auto-disconnect working again - failed with that
14 ##
15 ## Revision 1.14 2003/02/09 05:12:28 joko
16 ## + quoting of strings used in sql-queries!
17 ##
18 ## Revision 1.13 2003/01/30 22:27:05 joko
19 ## + added new abstract methods
20 ##
21 ## Revision 1.12 2003/01/30 21:46:32 joko
22 ## + fixed behaviour of AUTOLOAD-method
23 ##
24 ## Revision 1.11 2003/01/20 16:43:18 joko
25 ## + better argument-property merging
26 ## + debugging-output !!!
27 ## + abstract-dummy 'sub createChildNode'
28 ##
29 ## Revision 1.10 2003/01/19 02:31:51 joko
30 ## + fix to 'sub AUTOLOAD'
31 ##
32 ## Revision 1.9 2002/12/19 16:30:23 joko
33 ## + added 'sub dropDb' and 'sub rebuildDb' as croakers for concrete implementations of methods in proper handlers
34 ##
35 ## Revision 1.8 2002/12/13 21:48:35 joko
36 ## + sub _abstract_function
37 ##
38 ## Revision 1.7 2002/12/05 07:57:48 joko
39 ## + now using Tie::SecureHash as a base for the COREHANDLE
40 ## + former public COREHANDLE becomes private _COREHANDLE now
41 ##
42 ## Revision 1.6 2002/12/03 15:52:24 joko
43 ## + fix/feature: if dispatching to deep core method fails (is not declared), try method at Data::Storage - level
44 ##
45 ## Revision 1.5 2002/12/01 22:19:33 joko
46 ## + just disconnect if COREHANDLE exists
47 ##
48 ## Revision 1.4 2002/12/01 04:45:38 joko
49 ## + sub eraseAll
50 ## + sub createDb
51 ##
52 ## Revision 1.3 2002/11/29 04:58:20 joko
53 ## + Storage::Result now uses the same dispatching mechanism like Storage::Handler
54 ##
55 ## Revision 1.2 2002/10/17 00:08:07 joko
56 ## + bugfixes regarding "deep recursion" stuff
57 ##
58 ## Revision 1.1 2002/10/10 03:44:07 cvsjoko
59 ## + new
60 ## ------------------------------------------------------------------------
61
62
63 package Data::Storage::Handler::Abstract;
64
65 use strict;
66 use warnings;
67
68 use base qw( DesignPattern::Object );
69
70
71 use Data::Dumper;
72 use Tie::SecureHash;
73 #use Data::Storage::Handler;
74 use Hash::Merge qw( merge );
75
76 #use Log::Dispatch::Config;
77 #Log::Dispatch::Config->configure();
78
79 # get logger instance
80 my $logger;
81 eval('$logger = Log::Dispatch::Config->instance;');
82
83 #our $lock_info;
84
85 sub new {
86 my $invocant = shift;
87 my $class = ref($invocant) || $invocant;
88
89 # logging info about the actual handler called
90 $logger->debug( "$invocant->new( @_ )" ) if $logger;
91 #$logger->debug( __PACKAGE__ . "->" . "new()" );
92
93 # V1 - arguments become properties automagically / normal perl mode blessing
94 =pod
95 # autovivify passed-in arguments as future object attributes into to-be-blessed hash
96 my $self = { @_ };
97 # create object from blessed hash-reference
98 bless $self, $class;
99 =cut
100
101 #=pod
102 # V2 - maybe more convenient/secure? utilizing Damian Conway's Tie::SecureHash...
103 my $self = Tie::SecureHash->new(
104 $class,
105 # that's it:
106 'metainfo' => undef,
107 'lock_info' => undef,
108 '_COREHANDLE' => undef,
109 'meta' => undef,
110 'locator' => undef,
111 'dataStorageLayer' => undef,
112 'dbi' => undef,
113 # tries:
114 #'Data::Storage::Handler::Abstract::metainfo' => undef,
115 #'dataStorageLayer'
116 #'Data::Storage::Handler::Abstract::dataStorageLayer' => undef,
117 #'Data::Storage::Handler::Tangram::dataStorageLayer' => undef,
118 #'Data::Dumper::locator' => undef,
119 #$class . '::locator' => undef,
120 #'Data::Storage::Handler::Tangram::locator' => undef,
121 #'Data::Storage::Handler::DBI::locator' => undef,
122 #_protected => ,
123 #__private => ,
124 );
125 #=cut
126
127 # merge passed-in arguments to constructor as properties into already blessed secure object
128
129 # mungle arguments from array into hash - perl does the job ;)
130 #my %args = @_;
131 #my %args = ();
132
133 #print Dumper(@_);
134
135 # merge attributes one-by-one
136 # TODO: deep_copy? / merge_deep?
137 while (my $elemName = shift @_) {
138 #print "elemName: $elemName", "\n";
139 if (my $elemValue = shift @_) {
140 #print Dumper($elemValue);
141 #print "elemName=$elemName, elemValue=$elemValue", "\n";
142 $self->{$elemName} = $elemValue;
143 }
144 #$self->{$_} = $args{$_};
145 #$self->{$_} = $args{$_};
146 }
147
148 # V3 - rolling our own security (just for {COREHANDLE} - nothing else) - nope, Tie::SecureHash works wonderful
149 #my $self = { @_ };
150 #bless $self, $class;
151
152
153
154 # handle meta data
155 #my $metainfo = $self->getMetaInfo($class);
156 my $metainfo = $self->getMetaInfo();
157 if (!$metainfo->{disconnectMethod}) { $metainfo->{disconnectMethod} = 'disconnect'; }
158 # type?
159 $invocant =~ s/Data::Storage::Handler:://;
160 $metainfo->{type} = $invocant;
161
162 # direct accessible (non-protected) properties ( was: my $self = { }; )
163 $self->{metainfo} = $metainfo;
164
165 return $self;
166 }
167
168
169 # TODO: use NEXT.pm inside this mechanism (to avoid repetitions...)
170 sub AUTOLOAD {
171
172 # recursion problem to be avoided here!!!
173
174 # - problem: we get recursion-hangs!!! => perl stops with ...
175 # "Deep recursion on subroutine "Data::Storage::Handler::Abstract::AUTOLOAD" at [...]/libs/Data/Storage.pm line 38."
176
177 # - when: if we log to ourselves as a storage-implementation (e.g. via Log::Dispatch::Tangram)
178 # - why: debug-messages are on a very low level including every data-operation to "Data::Storage(::Handler::X)",
179 # so e.g. a "$storage->insert" would trigger another "$storage->insert" itself
180 # which leads to a infinite recursion loop (deep recursion)
181 # - solution: locks! (by Hack or (maybe) via Perl "local"s)
182
183 my $self = shift;
184
185 our $AUTOLOAD;
186 #return if $AUTOLOAD =~ m/::DESTROY$/;
187
188 # find out methodname
189 my $methodname = $AUTOLOAD;
190 $methodname =~ s/^.*:://;
191
192 #print "method: $methodname", "\n";
193
194 # TODO: document this! handler-private methods listed here will not be triggered (internal use)
195 # in this case, "exists" is a method reserved for Tie::SecureHash,
196 # which encapsulates the perl data structure (HASH) under this object
197 # this is to prevent deep recursion's
198 return if lc $methodname eq 'exists';
199
200 #print "$methodname - 1", "\n";
201
202 # TODO: enhance logging/debugging
203 #if (!$self->exists('COREHANDLE')) { return; }
204
205 # handle locking (hack)
206 if ($self->can('exists') && $self->exists('lock_info') && $self->{lock_info}->{last_method} && $methodname eq $self->{lock_info}->{last_method}) {
207 $self->{lock_info}->{log_lock} = 1;
208 } else {
209 $self->{lock_info}->{log_lock} = 0;
210 }
211 $self->{lock_info}->{last_method} = $methodname;
212
213 #print "$methodname - 2", "\n";
214
215 #print Dumper($self);
216 #exit;
217
218 # get corehandle instance from underlying handler
219 my $core = $self->getCOREHANDLE();
220
221 # test for COREHANDLE
222 #if (!$self->{_COREHANDLE}) {
223 #=pod
224 #if (!$self->exists('_COREHANDLE')) {
225 #if (!$self->{_COREHANDLE}) {
226 if (!$core) {
227
228 #print Dumper($self);
229 #exit;
230
231 my $handlertype = $self->{metainfo}->{type};
232 $handlertype ||= '';
233
234 my $err_msg_core = __PACKAGE__ . "[$handlertype]" . ": " . "COREHANDLE is undefined while trying to execute method \"$methodname\"";
235
236 #print $err_msg_core, "\n";
237
238 #if ($self->exists('lock_info') && !$self->{lock_info}->{log_lock}) {
239 $logger->error( $err_msg_core );
240 #}
241
242 return;
243
244 }
245 #=cut
246
247 =pod
248 if (!$methodname) {
249 die("Methodname is not defined!");
250 return;
251 }
252 =cut
253
254 #print "$methodname - 3", "\n";
255
256 # try to dispatch method-call to Storage::Handler::*
257 #if ($self->can($methodname)) {
258 #$logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->" . $methodname . "(@_)" );
259 #my $res = $self->$methodname(@_);
260 #if ($res) { return $res; }
261 #}
262
263 #print "$methodname - 4", "\n";
264
265 # try to dispatch method-call to COREHANDLE
266 # was:
267 #my $core = $self->{_COREHANDLE};
268 # is:
269 #my $core = $self->getCOREHANDLE();
270
271 #print Dumper($core);
272 #exit;
273
274 # was:
275 #if ($self->{_COREHANDLE}->can($methodname) || $self->{_COREHANDLE}->can("AUTOLOAD")) {
276 # is:
277 if ($core->can($methodname) || $core->can("AUTOLOAD")) {
278 #$logger->debug( __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );
279 #$lock_AUTOLOAD = 1 if ($methodname eq 'insert');
280 if (!$self->{lock_info}->{log_lock}) {
281 #print "method: $methodname", "\n";
282 my $type = $self->{metainfo}->{type};
283 $type ||= '';
284 # FIXME!
285 #$logger->debug( __PACKAGE__ . "[$type]" . "->" . $methodname . "(@_)" );
286 $logger->debug( __PACKAGE__ . "[$type]" . "->" . $methodname );
287 } else {
288 # AUTOLOAD - sub is locked to prevent deep recursions if (e.g.) db-inserts cause log-actions to same db itself
289 }
290 #$lock_AUTOLOAD = 0;
291 #$logger->log( level => 'debug', message => __PACKAGE__ . "->" . $methodname . " (AUTOLOAD)" );
292
293 #print "calling: $methodname", "\n";
294
295 # method calls making it until here will get dispatched to the proper handler
296 return $core->$methodname(@_);
297
298 } elsif ($self->can($methodname)) {
299 # try to call specified method inside our or inherited module(s) scope(s)
300 return $self->$methodname(@_);
301 }
302
303 }
304
305 sub DESTROY {
306 my $self = shift;
307
308 return;
309
310 $logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->DESTROY" );
311
312 my $disconnectMethod = $self->{metainfo}->{disconnectMethod};
313 print "meth: ", $disconnectMethod, "\n";
314
315 #$disconnectMethod && $self->{_COREHANDLE} && ( $self->{_COREHANDLE}->$disconnectMethod() );
316 $self->{_COREHANDLE}->$disconnectMethod();
317 #$self->$disconnectMethod();
318
319 #my $core1 = $self->getCOREHANDLE() if $self->can('getCOREHANDLE');
320 #$core1->$disconnectMethod();
321
322 return;
323
324 print "DESTROY-1", "\n";
325 #if ($self->{__COREHANDLE}) {
326 #if ($self->exists('_COREHANDLE')) {
327
328 # get corehandle instance from underlying handler
329 my $core;
330 $core = $self->getCOREHANDLE() if $self->can('getCOREHANDLE');
331
332 #if ($self->{STORAGEHANDLE}) {
333 if ($core) {
334 print "DESTROY-2", "\n";
335 $logger->debug( __PACKAGE__ . "[$self->{metainfo}->{type}]" . "->DESTROY" );
336
337 my $disconnectMethod = $self->{metainfo}->{disconnectMethod};
338
339 # call "disconnect" or alike on COREHANDLE
340 # was: $self->{COREHANDLE}->disconnect();
341 $disconnectMethod && $self->{_COREHANDLE} && ( $self->{_COREHANDLE}->$disconnectMethod() );
342
343 undef $self->{_COREHANDLE};
344 }
345 }
346
347 sub _typeCheck2 {
348 my $type = shift;
349 print "type: $type";
350 eval("use Data::Storage::$type;");
351 }
352
353
354 # ====================================================
355 # PUBLIC METHODS
356 # ====================================================
357
358 sub existsChildNode {
359 my $self = shift;
360 my $nodename = shift;
361
362 # TODO: don't use $self->{meta}->{childnodes} directly in here
363 # get it returned from $self->getChildNodes()!!!
364
365 $logger->debug( __PACKAGE__ . "->existsChildNode( nodename=$nodename )" );
366 $self->getChildNodes() unless $self->{meta}->{childnodes};
367
368 # quote this, it might contain meta characters which don't work in a regex
369 $nodename = quotemeta($nodename);
370
371 # trace
372 #print Dumper($self->{meta});
373 #print "nodename: $nodename", "\n";
374
375 # FIXME: use "/i" only on win32-systems!
376 my $result = grep(m/$nodename/i, @{$self->{meta}->{childnodes}});
377
378 return $result;
379 }
380
381 sub connect_tmp {
382
383 # my $self = shift;
384 # my $connectionString = shift;
385 # # todo: patch connectionString to $args
386 # _typeCheck($self->{args}{type});
387
388 }
389
390
391 # ====================================================
392 # CONCRETE METHOD DUMMIES (croaking via "$logger" by calling "_abstract_function")
393 # ====================================================
394
395 # TODO:
396 # - abstract "abstract methods" to list/hash to be used in AUTOLOAD
397 # e.g.: my @ABSTRACT_METHODS = (qw( connect sendCommand getChildNodes ));
398 # use Class::XYZ (Construct)
399 # - build them via anonymous subs
400 # - introduce them via symbols
401
402 sub getCOREHANDLE {
403 my $self = shift;
404 $self->_abstract_function('getCOREHANDLE');
405 }
406
407 sub sendCommand {
408 my $self = shift;
409 $self->_abstract_function('sendCommand');
410 }
411
412 sub createChildNode {
413 my $self = shift;
414 $self->_abstract_function('createChildNode');
415 }
416
417 sub existsChildNode_tmp {
418 my $self = shift;
419 $self->_abstract_function('existsChildNode');
420 }
421
422 sub getChildNodes {
423 my $self = shift;
424 $self->_abstract_function('getChildNodes');
425 }
426
427 sub configureCOREHANDLE {
428 my $self = shift;
429 $self->_abstract_function('configureCOREHANDLE');
430 }
431
432 sub getMetaInfo {
433 my $self = shift;
434 $self->_abstract_function('getMetaInfo');
435 return;
436 }
437
438 sub getListUnfiltered {
439 my $self = shift;
440 $self->_abstract_function('getListUnfiltered');
441 return;
442 }
443
444 sub getListFiltered {
445 my $self = shift;
446 $self->_abstract_function('getListFiltered');
447 return;
448 }
449
450 sub sendQuery {
451 my $self = shift;
452 $self->_abstract_function('sendQuery');
453 return;
454 }
455
456 sub connect {
457 my $self = shift;
458 $self->_abstract_function('connect');
459 return;
460 }
461
462 sub testIntegrity {
463 my $self = shift;
464 $self->_abstract_function('testIntegrity');
465 return;
466 }
467
468 sub quoteSql {
469 my $self = shift;
470 $self->_abstract_function('quoteSql');
471 return;
472 }
473
474 sub eraseAll {
475 my $self = shift;
476 $self->_abstract_function('eraseAll');
477 return;
478 }
479
480 sub createDb {
481 my $self = shift;
482 $self->_abstract_function('createDb');
483 return;
484 }
485
486 sub dropDb {
487 my $self = shift;
488 $self->_abstract_function('dropDb');
489 return;
490 }
491
492 sub rebuildDb {
493 my $self = shift;
494 $self->_abstract_function('rebuildDb');
495 return;
496 }
497
498 sub getDbName {
499 my $self = shift;
500 $self->_abstract_function('getDbName');
501 return;
502 }
503
504 sub testAvailability {
505 my $self = shift;
506 $self->_abstract_function('testAvailability');
507 return;
508 }
509
510 sub isConnected {
511 my $self = shift;
512 $self->_abstract_function('isConnected');
513 return;
514 }
515
516 sub testDsn {
517 my $self = shift;
518 $self->_abstract_function('testDsn');
519 return;
520 }
521
522 1;

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed