/[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.14 - (show annotations)
Sun Feb 9 05:12:28 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.13: +20 -4 lines
+ quoting of strings used in sql-queries!

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

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